链接 : http://www.lydsy.com/JudgeOnline/problem.php?id=1500
如果都做到这题了,就不多说了
有很多的注意点,代码中有注释
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int inf = ~0u>>2; #define L ch[x][0] #define R ch[x][1] #define KT (ch[ ch[rt][1] ][0]) const int maxn = 500010; struct SplayTree { int sz[maxn]; int ch[maxn][2]; int pre[maxn]; int rt,top,top2; int que[maxn],ss[maxn]; inline int max(int a,int b) { return a>b?a:b; } inline void down(int x){ if(!x) return ; if(flip[x]) { flip[ L ] ^= 1; flip[ R ] ^= 1; swap(L,R); swap(ls[x],rs[x]); flip[x] = false ; } if(same[x]) {//注意防止将0节点赋值 if(L) same[ L ] = 1; if(R) same[ R ] = 1; if(L)val[ L ] = val[x]; if(R)val[ R ] = val[x]; if(L)sum[ L ] = val[x] * sz[ L ]; if(R)sum[ R ] = val[x] * sz[ R ]; if(L)mx_sum[L] = ls [ L ] = rs[ L ] = max(val[x],sum[ L ]); if(R)mx_sum[R] = ls [ R ] = rs[ R ] = max(val[x],sum[ R ]); same[x] = false ; } } inline void up(int x){ if(!x) return; if(L) down(L); if(R) down(R);//关键所在,儿子节点的信息必须先down下去,不然有可能得到的mx_sum不是真实的 sz[x] = 1 + sz[ L ] + sz[ R ]; sum[x] = val[x] + sum[L] + sum[R]; ls[x] = max( ls[L] , sum[L] + val[x] + max(ls[R],0)); rs[x] = max( rs[R] , sum[R] + val[x] + max(rs[L],0)); mx_sum[x] = max(rs[L],0) + val[x] + max(ls[R],0); mx_sum[x] = max(mx_sum[x],max(mx_sum[L],mx_sum[R])); } inline void Rotate(int x,int f){ int y=pre[x]; down(y); down(x); ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x; ch[x][f] = y; pre[y] = x; up(y); } inline void Splay(int x,int goal){//将x旋转到goal的下面 down(x);//防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了 while(pre[x] != goal){ down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变 if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x); else { int y=pre[x],z=pre[y]; int f = (ch[z][0]==y); if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f); else Rotate(y,f),Rotate(x,f); } } up(x); if(goal==0) rt=x; } inline void RTO(int k,int goal){//将第k位数旋转到goal的下面 int x=rt; down(x); while(sz[ L ]+1 != k) { if(k < sz[ L ] + 1 ) x=L; else { k-=(sz[ L ]+1); x = R; } down(x); } Splay(x,goal); } inline void Newnode(int &x,int c,int f){ if(top2) x = ss[--top2]; else x = ++top; L = R = 0; pre[x]=f; sz[x] = 1; val[x] = c; sum[x] = c; flip[x] = same[x] = false; ls[x] = rs[x] = mx_sum[x] = c; } inline void build(int &x,int l,int r,int f){ if(l>r) return ; int m=l+r>>1; Newnode(x,num[m],f); build(L , l , m-1 , x); build(R , m+1 , r , x); pre[x]=f; up(x); } inline void debug(){ vist(rt); puts(""); } inline void init(int n){ ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; rt=top=top2=0; flip[0]=false; val[0]=0; sum[0]=0; same[0] = false; ls[0] = rs[0] = mx_sum[0] = -inf; for(int i = 1 ; i <= n ; i++) scanf("%d" , &num[i]); Newnode(rt,-inf,0); Newnode(ch[rt][1],-inf,rt); sz[rt]=2; build(KT,1,n,ch[rt][1]); up(ch[rt][1]); up(rt); } inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存 int father = pre[x]; int head = 0 , tail = 0; for (que[tail++] = x ; head < tail ; head ++) { ss[top2 ++] = que[head]; if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0]; if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1]; } ch[ father ][ ch[father][1] == x ] = 0; up(father); } void vist(int x){ if(x){ printf("结点%2d : 左儿子 %2d 右儿子 %2d val : %5d mxsum : %5d flip : %5d same : %d\n",x, L,R,val[x],mx_sum[x],flip[x],same[x]); vist(L); vist(R); } } inline void GET_SUM() { scanf("%d%d",&pos,&tot); int l=pos,r=pos+tot-1; RTO(l,0); RTO(r+2,rt); printf("%d\n",sum[KT]); } inline void DELETE() { scanf("%d%d",&pos,&tot); int l=pos,r=tot+pos-1; RTO(l,0); RTO(r+2,rt); erase(KT); KT=0; up(ch[rt][1]); up(rt); } inline void INSERT() { scanf("%d%d",&pos,&tot); for(int i=1;i<=tot;i++) scanf("%d",&num[i]); RTO(pos+1,0); RTO(pos+2,rt); build(KT,1,tot,ch[rt][1]); up(ch[rt][1]); up(rt); } inline void MAKE_SAME() { int c; scanf("%d%d%d",&pos,&tot,&c); int l=pos,r=pos+tot-1; RTO(l,0); RTO(r+2,rt); same[KT] = true; val[KT] = c; sum[KT] = sz[KT] * c; mx_sum[KT] = max( c , sum[KT] ); ls[KT] = max(c , sum[KT]); rs[KT] = max(c , sum[KT]); up(ch[rt][1]); up(rt); } void print(int x) { if(x) { down(x); print(L); if(val[x]>-10000) { if(flag) printf(" "); printf("%d",val[x]); flag=1; } print(R); } } inline void OUT() { flag=0; print(rt); printf("\n"); } inline void REVERSE() { scanf("%d%d",&pos,&tot); int l=pos,r=pos+tot-1; RTO(l,0); RTO(r+2,rt); flip[KT]^=1; } inline void MAX_SUM() { RTO(1,0) ; RTO(sz[rt],rt); printf("%d\n",mx_sum[KT]); } int flag; int pos,tot; bool flip[maxn]; int val[maxn]; int num[maxn]; int sum[maxn];//求和 bool same[maxn];//统一修改为一个数 int ls[maxn];//最大前缀和 int rs[maxn];//最大后缀和 int mx_sum[maxn];//最大子列和 }spt; int main() { int n,m,pos,tot; scanf("%d%d",&n,&m); spt.init(n); char op[50]; while(m--) { scanf("%s",op); if(strcmp(op,"GET-SUM") == 0) { spt.GET_SUM(); } else if(strcmp(op,"MAX-SUM") == 0) { spt.MAX_SUM(); } else if(strcmp(op,"INSERT") == 0) { spt.INSERT(); } else if(strcmp(op,"DELETE") == 0) { spt.DELETE(); } else if(strcmp(op,"MAKE-SAME") == 0) { spt.MAKE_SAME(); } else if(strcmp(op,"OUT") == 0) { spt.OUT(); } else if(strcmp(op,"DEBUG") == 0){ spt.debug(); } else if(strcmp(op,"NEWTREE")==0){ spt.debug(); } else { spt.REVERSE(); } } return 0; }