TYVJ2195 序列终结者
三种操作
1.区间加上某个数 增加add域表示加值懒惰标记
2.区间翻转 增加rev域表示翻转懒惰标记
3.返回区间最值 增加mx域表示以当前节点为根节点的子树的最大值
更新的 时候一定要先把当前节点更新,再加懒惰标记。
pushup的时候最好是判断下左右节点是否存在(这个题是必须判断),这是一个很良好的习惯
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int maxn = 59993; 5 int fa[maxn],son[2][maxn],mx[maxn],add[maxn],lz[maxn],val[maxn],siz[maxn]; 6 int root,tot; 7 void pushup(int x){ 8 int l = son[0][x],r = son[1][x]; 9 mx[x] = val[x]; 10 if(l)mx[x] = max(mx[x],mx[l]); 11 if(r)mx[x] = max(mx[x],mx[r]); 12 siz[x] = siz[l]+siz[r]+1; 13 } 14 void pushdown(int x){ 15 int l = son[0][x],r = son[1][x]; 16 if(add[x]){ 17 val[l]+=add[x];val[r]+=add[x]; 18 mx[l]+=add[x];mx[r]+=add[x]; 19 add[l]+=add[x];add[r]+=add[x]; 20 add[x] = 0; 21 } 22 if(lz[x]){ 23 swap(son[0][l],son[1][l]); 24 swap(son[0][r],son[1][r]); 25 lz[r]^=1;lz[l]^=1; 26 lz[x] = 0; 27 } 28 } 29 void rota(int w,int x){ 30 int y = fa[x]; 31 son[!w][y] = son[w][x]; 32 if(son[w][x])fa[son[w][x]] = y; 33 fa[x] = fa[y]; 34 if(fa[y])son[y==son[1][fa[y]]][fa[y]] = x; 35 fa[y] = x; 36 son[w][x] = y; 37 pushup(y);pushup(x); 38 } 39 void splay(int x,int y){ 40 while(fa[x]!=y){ 41 if(fa[fa[x]]==y)rota(x==son[0][fa[x]],x); 42 else { 43 int w = fa[x]==son[0][fa[fa[x]]]; 44 if(x==son[w][fa[x]]){ 45 rota(!w,x);rota(w,x); 46 } 47 else { 48 rota(w,fa[x]);rota(w,x); 49 } 50 } 51 } 52 if(y==0)root = x; 53 } 54 int getk(int k){ 55 int x = root; 56 while(1){ 57 pushdown(x); 58 if(k==siz[son[0][x]]+1)return x; 59 if(k<=siz[son[0][x]])x = son[0][x]; 60 else { 61 k-=(siz[son[0][x]]+1); 62 x = son[1][x]; 63 } 64 } 65 } 66 int query(int l,int r){ 67 int x = getk(l-1),y = getk(r+1); 68 splay(x,0);splay(y,x); 69 return mx[son[0][y]]; 70 } 71 void rev(int l,int r){ 72 int x = getk(l-1),y = getk(r+1); 73 splay(x,0);splay(y,x); 74 int z = son[0][y]; 75 swap(son[0][z],son[1][z]); 76 lz[z]^=1; 77 } 78 void update(int l,int r,int v){ 79 int x = getk(l-1),y = getk(r+1); 80 splay(x,0);splay(y,x); 81 val[son[0][y]]+=v; 82 mx[son[0][y]]+=v; 83 add[son[0][y]]+=v; 84 } 85 int main() 86 { 87 int n,m;scanf("%d%d",&n,&m); 88 for(int i = 1;i<=n+2;++i){ 89 if(i==1){ 90 root = ++tot; 91 siz[root] = 1; 92 continue; 93 } 94 son[0][++tot] = root; 95 fa[root] = tot; 96 siz[tot] = siz[root]+1; 97 root = tot; 98 } 99 while(m--){ 100 int op,l,r,v;scanf("%d%d%d",&op,&l,&r); 101 if(op==1){ 102 scanf("%d",&v); 103 update(l+1,r+1,v); 104 } 105 else if(op==2)rev(l+1,r+1); 106 else printf("%d\n",query(l+1,r+1)); 107 } 108 return 0; 109 }
弱者究竟为何而战?!