BZOJ1500: [NOI2005]维修数列
妈呀,写的我心态崩了,注意以下几点:
1.标记下放时应该立即更新子节点,才能pushup更新当前结点(此时实际上在当前结点的标记已经使用过了)。
2.最好类似线段树的建树方法,否则容易RE。
3.写个回收。
4.我这splay写的是菜出狗屎了,在rotate里面pushdown,妈呀,就是因为没注意第一点,而且常数贼大,虽然可以过。
5.其他就是加两个结点0,n+1,好处理就行了。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <cstring> #include <string> #include <bitset> #include <stack> #include <set> #include <map> #include <list> #include <assert.h> using namespace std; #define e exp(1.0) typedef long long ll; #define MAXN 500005 #define mod 100000007 #define INF 1000000000 #define fe(i,st,en) for(i = (st);i <= (en);++i) #define fne(i,st,en) for(i = (st);i < (en);++i) #define ri register int #define db double int n,b[MAXN]; struct Splay { int a[MAXN], sz[MAXN], s[MAXN], lazy[MAXN],rev[MAXN], son[MAXN][2],lma[MAXN],rma[MAXN], ma[MAXN], fa[MAXN], root; int sta[MAXN], coll[MAXN], coll_top, _sz; void pushup(int o) {//o后代的信息修改后调用 s[o] = a[o], sz[o] = 1; s[o] += s[son[o][0]], sz[o] += sz[son[o][0]]; s[o] += s[son[o][1]], sz[o] += sz[son[o][1]]; lma[o] = max(0, max(s[son[o][0]] + a[o] + lma[son[o][1]], lma[son[o][0]]));//该点表示的的区间前缀最大和 rma[o] = max(0, max(s[son[o][1]] + a[o] + rma[son[o][0]], rma[son[o][1]]));//该点表示的的区间后缀最大和 ma[o] = max(lma[son[o][1]]+rma[son[o][0]]+a[o], max(ma[son[o][0]], ma[son[o][1]])); } int build(int o,int l,int r,int v) { if (l > r) return 0; int mid = (l + r) >> 1; o = newnode(o, v, b[mid]); build(o,l,mid-1,0); build(o, mid+1, r,1); pushup(o); return o; } void pushdown(int o) {//查找询问前调用 if (rev[o]) { swap(son[o][0], son[o][1]); swap(lma[o], rma[o]); if (son[o][0]) rev[son[o][0]] ^= 1; if (son[o][1]) rev[son[o][1]] ^= 1; rev[o] = 0; } if (lazy[o] != -INF) { a[o] = lazy[o], s[o] = lazy[o] * sz[o], ma[o] = max(lazy[o], lazy[o] * sz[o]);//lazy为负则max为lazy[o],否则为lazy[o]*sz[o] if (lazy[o] < 0) lma[o] = rma[o] = 0; else lma[o] = rma[o] = ma[o]; if (son[o][0]) lazy[son[o][0]] = lazy[o]; if (son[o][1]) lazy[son[o][1]] = lazy[o]; lazy[o] = -INF; } } void change(int o, int fo, int v) { son[fo][v] = o, fa[o] = fo; } int newnode(int fo,int v,int x) { int o; if (coll_top) o = coll[coll_top--]; else o = _sz++; son[o][0] = son[o][1] = rev[o] = 0, sz[o] = 1, lazy[o] = -INF, ma[o] = s[o] = a[o] = x; if (x > 0) lma[o] = rma[o] = x; else lma[o] = rma[o] = 0; change(o, fo, v); return o; } int isright(int o, int fo) { return son[fo][1] == o; } void rotate(int o) { int f = fa[o], g = fa[f], v = isright(o, f); change(o, g, isright(f, g)); if (root == f) root = o; change(son[o][v ^ 1], f, v); change(f, o, v ^ 1); pushdown(son[f][0]),pushdown(son[f][1]),pushup(f); } void splay(int o,int fo) { while (fa[o] != fo) { int f = fa[o], g = fa[f]; if (g != fo) (isright(o, f) ^ isright(f, g)) ? rotate(o) : rotate(f); rotate(o); } pushdown(son[o][0]), pushdown(son[o][1]); pushup(o); } int findpos(int o,int pos) {//找pos对应结点的过程中,该结点o和root之间的结点均调用pushdown,可能这个结点,结果死循环! pushdown(o);//更新翻转标记 if (sz[son[o][0]] + 1 == pos) return o; if (sz[son[o][0]] >= pos) return findpos(son[o][0], pos); return findpos(son[o][1], pos-sz[son[o][0]]-1); } void insert(int pos,int tot) { splay(findpos(root, pos + 1), 0); splay(findpos(root, pos + 2), root);//r翻转到root右儿子 for (ri i = 1; i <= tot; ++i) scanf("%d", b + i); int o = build(0, 1, tot, 0); change(o, son[root][1], 0); pushup(son[root][1]); pushup(root); n += tot; } void del(int pos, int tot) { splay(findpos(root, pos),0);//l-1翻转到root splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子 int o = son[son[root][1]][0], top = 0; sta[++top] = o; while (top) { int t = sta[top--]; coll[++coll_top] = t; if (son[t][0]) sta[++top] = son[t][0]; if (son[t][1]) sta[++top] = son[t][1]; } son[son[root][1]][0] = 0; pushup(son[root][1]); pushup(root); n -= tot; } void update(int pos, int tot, int x) { splay(findpos(root, pos), 0);//l-1翻转到root splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子 lazy[son[son[root][1]][0]] = x; pushdown(son[son[root][1]][0]); pushup(son[root][1]); pushup(root);//把lazy pushdown后更新root和root的右儿子信息 } void reverse(int pos, int tot) { splay(findpos(root, pos), 0);//l-1翻转到root splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子 rev[son[son[root][1]][0]] ^= 1;//翻转会改变祖辈信息 pushdown(son[son[root][1]][0]); pushup(son[root][1]), pushup(root);// } int querySum(int pos, int tot) { splay(findpos(root, pos), 0);//l-1翻转到root splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子 return s[son[son[root][1]][0]]; } int queryMax() { splay(findpos(root, 1), 0);//l-1翻转到root splay(findpos(root, n+2), root);//r+1翻转到root右儿子 return ma[son[son[root][1]][0]]; } }T; int main() { //freopen("C:\\Users\\Administrator\\Desktop\\input.in", "r", stdin); //cout << (1 << 30) - 1 << endl; int m, x, p, k; char s[20]; ri i; scanf("%d%d", &n, &m); fe(i, 1, n) scanf("%d", b+i); b[0] = b[n + 1] = T.ma[0] = T.a[0] = T.lazy[0] = -INF; T._sz = 1, T.root = 1; T.build(0,0,n+1,0); //cout <<"T._sz:"<< T._sz << endl; fe(i, 1, m) { scanf("%s", s); if (s[0] == 'I') { scanf("%d%d", &p, &k); T.insert(p, k); } else if (s[0] == 'D') scanf("%d%d", &p, &k),T.del(p, k); else if (s[0] == 'R') scanf("%d%d", &p, &k),T.reverse(p, k); else if (s[0] == 'G') scanf("%d%d", &p, &k),printf("%d\n", T.querySum(p, k)); else if(s[2] == 'K') scanf("%d%d%d", &p, &k,&x),T.update(p, k, x); else printf("%d\n", T.queryMax()); } return 0; }