[NOI2005]维护数列

[LuoguP2042]

肝了一晚上和一上午,先把代码发了,等有时间(假期?)把较为详细的解释补一下(

Code:

  1 #include <bits/stdc++.h>
  2 #define ll long long
  3 #define L(x) e[x].son[0]
  4 #define R(x) e[x].son[1]
  5 #define lx(x) e[x].left
  6 #define rx(x) e[x].right
  7 #define mx(x) e[x].mx
  8 #define sum(x) e[x].sum
  9 using namespace std;
 10 const int N = 1e6 + 7;
 11 const int inf = 0x3f3f3f3f;
 12 ll read() {
 13     ll re = 0, f = 1;
 14     char ch = getchar();
 15     while (ch < '0' || ch > '9') {if (ch == '-') f = -f; ch = getchar();}
 16     while ('0' <= ch && ch <= '9') {re = re * 10 + ch - '0'; ch = getchar();}
 17     return re * f;
 18 }
 19 int n, m, root, cnt;
 20 struct node{
 21     int val, father;
 22     int son[2];
 23     int siz;
 24     int sum, mx;
 25     int left, right;
 26     bool tag, rev;
 27 }e[N];
 28 int top, a[N], id[N], rub[N];
 29 void update(int x) {
 30     int l = L(x), r = R(x);
 31     sum(x) = sum(l) + sum(r) + e[x].val;
 32     e[x].siz = e[l].siz + e[r].siz + 1;
 33     mx(x) = max(mx(l), max(mx(r), rx(l) + e[x].val + lx(r)));
 34     lx(x) = max(lx(l), sum(l) + e[x].val + lx(r));
 35     rx(x) = max(rx(r), sum(r) + e[x].val + rx(l));
 36 }
 37 void pushdown(int x) {
 38     int l = L(x), r = R(x);
 39     if (e[x].tag) {
 40         e[x].tag = e[x].rev = false;
 41         if (l) {
 42             e[l].tag = true, e[l].val = e[x].val, sum(l) = e[x].val * e[l].siz;
 43             lx(l) = rx(l) = max(sum(l), 0);
 44             mx(l) = max(sum(l), e[l].val);
 45         }
 46         if (r) {
 47             e[r].tag = true, e[r].val = e[x].val, sum(r) = e[x].val * e[r].siz;
 48             lx(r) = rx(r) = max(sum(r), 0);
 49             mx(r) = max(sum(r), e[r].val);
 50         }
 51     }
 52     if (e[x].rev) {
 53         e[x].rev = false;
 54         e[l].rev ^= 1, e[r].rev ^= 1;
 55         swap(lx(l), rx(l)), swap(lx(r), rx(r));
 56         swap(L(l), R(l)), swap(L(r), R(r));
 57     }
 58 }
 59 void connect(int x, int fa, int Son) {
 60     e[x].father = fa;
 61     e[fa].son[Son] = x;
 62 }
 63 int identify(int x) {
 64     return L(e[x].father) == x ? 0 : 1;
 65 }
 66 void rotate(int x) {
 67     int fa = e[x].father, fason = identify(x);
 68     int gfa = e[fa].father, gfason = identify(fa);
 69     int B = e[x].son[fason ^ 1];
 70     connect(B, fa, fason), connect(fa, x, fason ^ 1);
 71     connect(x, gfa, gfason);
 72     update(fa), update(x);
 73 }
 74 void splay(int now, int to) {
 75     int tofa = e[to].father;
 76     while (e[now].father != tofa) {
 77         int fa = e[now].father, gfa = e[fa].father;
 78         if (gfa != tofa) {
 79             rotate(identify(now) == identify(fa) ? fa : now);
 80         }
 81         rotate(now);
 82     }
 83     if (to == root) root = now;
 84 }
 85 int kth(int rank) {
 86     int now = root;
 87     while (true) {
 88         pushdown(now);
 89         if (e[L(now)].siz >= rank) {
 90             now = L(now);
 91         } else {
 92             rank -= e[L(now)].siz + 1;
 93             if (!rank) return now;
 94             now = R(now);
 95         }
 96     }
 97 }
 98 int split(int k, int tot) {
 99     int x = kth(k), y = kth(k + tot + 1);
100     splay(x, root), splay(y, R(x));
101     return L(y);
102 }
103 void Reverse(int k, int tot) {
104     int x = split(k, tot), y = e[x].father;
105     if (!e[x].tag) {
106         e[x].rev ^= 1;
107         swap(L(x), R(x));
108         swap(lx(x), rx(x));
109         update(y), update(e[y].father);
110     }
111 }
112 int rubbish() {
113     if (!top) return ++cnt;
114     int x = rub[top--];
115     return x;
116 }
117 void build(int l, int r, int fa) {
118     int mid = (l + r) / 2;
119     int now = id[mid], pre = id[fa];
120     if (l == r) {
121         mx(now) = sum(now) = a[l];
122         e[now].tag = e[now].rev = false;
123         lx(now) = rx(now) = max(a[l], 0);
124         e[now].siz = 1;
125     }
126     if (l < mid) build(l, mid - 1, mid);
127     if (r > mid) build(mid + 1, r, mid);
128     e[now].val = a[mid], e[now].father = pre, e[now].tag = 0;
129     update(now);
130     e[pre].son[mid >= fa] = now;
131 }
132 void Insert(int k, int tot) {
133     for (int i = 1; i <= tot; i++) a[i] = read();
134     for (int i = 1; i <= tot; i++) {
135         id[i] = rubbish();
136     }
137     build(1, tot, 0);
138     int z = id[(1 + tot) / 2];
139     int x = kth(k + 1), y = kth(k + 2);
140     splay(x, root), splay(y, R(x));
141     connect(z, y, 0);
142     update(y), update(x);
143 }
144 void remove(int x) {
145     if (L(x)) remove(L(x));
146     if (R(x)) remove(R(x));
147     rub[++top] = x;
148     e[x].father = L(x) = R(x) = e[x].tag = e[x].rev = 0;
149 }
150 void Erase(int k, int tot) {
151     int x = split(k, tot), y = e[x].father;
152     remove(x);
153     L(y) = 0;
154     update(y), update(e[y].father);
155 }
156 void change(int k, int tot, int v) {
157     int x = split(k, tot), y = e[x].father;
158     e[x].val = v, e[x].tag = true;
159     sum(x) = e[x].siz * v;
160     lx(x) = rx(x) = max(sum(x), 0);
161     mx(x) = max(sum(x), e[x].val);
162     update(y), update(e[y].father);
163 }
164 int query(int k, int tot) {
165     int x = split(k, tot);
166     return sum(x);
167 }
168 int main () {
169     n = read(), m = read();
170     mx(0) = a[1] = a[n + 2] = -inf;
171     for (int i = 1; i <= n; i++) a[i + 1] = read();
172     for (int i = 1; i <= n + 2; i++) id[i] = i;
173     build(1, n + 2, 0);
174     root = (n + 3) / 2;
175     cnt = n + 2;
176     int k, tot, v;
177     string s;
178     while (m--) {
179         cin >> s;
180         if (s != "MAX-SUM") {
181             k = read(), tot = read();
182         } else {
183             printf("%d
", mx(root));
184         }
185         if (s == "INSERT") Insert(k, tot);
186         if (s == "DELETE") Erase(k, tot);
187         if (s == "MAKE-SAME") {
188             v = read();
189             change(k, tot, v);
190         }
191         if (s == "REVERSE") Reverse(k, tot);
192         if (s == "GET-SUM") printf("%d
", query(k, tot));
193     }
194     return 0;
195 }
View Code