bzoj 1500 维修数列
Splay的BOSS级别的题目,几乎包含了所有区间维护的操作,对于想要提高代码熟练度的人来说这个题非常值得一写。
首先我们要维护的域是:size,sum,la(左max),ra(右max),ma(整体max)更新的时候用这些域更新就行,注意下传的时候也要更新响应域值。
对于那些恶心操作,我就挨个说一下吧:
注:标准结构:区间右端点+1(R)为根,区间左端点-1(L)为根的左儿子,这样目标区间就是L的右儿子,这种形式以后都用"标准结构"代替。
插入操作:先把需要插入的序列建成一个小平衡树(递归),转出标准结构,插到L的右儿子上就行了。
删除操作:转出标准结构,把L的右儿子切下来就行了(注意因为要回收空间,所以还是把要切的子树遍历了一遍,把这颗树上的节点标号入栈)。
覆盖操作:转出标准结构,把L的右儿子打上覆盖标记cov(以后下传的时候把节点的值改为cov的值,sum变为cov*size,la=ra=ma变为cov和sum中较大的一个,因为有负数的情况)
翻转操作:转出标准结构,把L的右儿子打上翻转标记rev(以后下传的时候要交换左右儿子并且交换la和ra)
求和操作:转出标准结构,答案就是L的右儿子的sum
最大值操作:转出标准结构,答案就是L的右儿子的ma
区间操作的时候一定要明白一点,就是打标记的同时做修改,就是说当一个点带了标记的时候,它已经被修改过了。
这个题还是做了我不少时间的。
repairnum
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 1000000 7 #define inf 2147483646 8 using namespace std; 9 int c[maxn][2],fa[maxn]; 10 int a[maxn],key[maxn],sum[maxn],la[maxn],ra[maxn],ma[maxn],cov[maxn],size[maxn]; 11 int q[maxn]; 12 bool rev[maxn]; 13 int n,m,tot,num,rot,st,ed,tail; 14 15 void update(int x) 16 { 17 if (!x) return; 18 la[x]=max(la[c[x][0]],sum[c[x][0]]+key[x]+max(0,la[c[x][1]])); 19 ra[x]=max(ra[c[x][1]],sum[c[x][1]]+key[x]+max(0,ra[c[x][0]])); 20 ma[x]=max(max(ma[c[x][0]],ma[c[x][1]]),key[x]+max(0,ra[c[x][0]])+max(0,la[c[x][1]])); 21 sum[x]=sum[c[x][0]]+sum[c[x][1]]+key[x]; 22 size[x]=size[c[x][0]]+size[c[x][1]]+1; 23 } 24 25 void reverse(int x) 26 { 27 if (!x) return; 28 swap(c[x][0],c[x][1]); 29 swap(la[x],ra[x]); 30 rev[x]^=1; 31 } 32 33 void recover(int x,int z) 34 { 35 if (!x) return ; 36 key[x]=cov[x]=z; 37 sum[x]=size[x]*z; 38 la[x]=ra[x]=ma[x]=max(z,sum[x]); 39 } 40 41 void down(int x) 42 { 43 if (!x) return; 44 if (rev[x]) 45 { 46 reverse(c[x][0]); 47 reverse(c[x][1]); 48 rev[x]=0; 49 } 50 if (cov[x]!=-inf) 51 { 52 recover(c[x][0],cov[x]); 53 recover(c[x][1],cov[x]); 54 cov[x]=-inf; 55 } 56 } 57 58 void relax(int x,int rot) 59 { 60 if (x!=rot) relax(fa[x],rot); 61 down(x); 62 } 63 64 void rotate(int x,int &rot) 65 { 66 int y=fa[x],z=fa[y]; 67 int p=(c[y][1]==x),q=p^1; 68 if (y==rot) rot=x; 69 else if (c[z][0]==y) c[z][0]=x; else c[z][1]=x; 70 fa[x]=z; fa[y]=x; fa[c[x][q]]=y; 71 c[y][p]=c[x][q]; c[x][q]=y; 72 update(y); 73 } 74 75 void splay(int x,int &rot) 76 { 77 relax(x,rot); 78 while (x!=rot) 79 { 80 int y=fa[x], z=fa[y]; 81 if (y!=rot) 82 if ((c[y][0]==x)xor(c[z][0]==y)) rotate(x,rot); else rotate(y,rot); 83 rotate(x,rot); 84 } 85 update(x); 86 } 87 88 int pick() 89 { 90 if (tail) return q[tail--]; 91 else return ++num; 92 } 93 94 int setup(int x) 95 { 96 int t=pick(); 97 key[t]=a[x]; 98 cov[t]=-inf; 99 rev[t]=0; 100 la[t]=ra[t]=ma[t]=-inf; 101 return t; 102 } 103 104 int build(int l,int r) 105 { 106 int mid=(l+r)>>1,left=0,right=0; 107 if (l<mid) left=build(l,mid-1); 108 int t=setup(mid); 109 if (r>mid) right=build(mid+1,r); 110 if (left) c[t][0]=left,fa[left]=t; 111 if (right)c[t][1]=right,fa[right]=t; 112 update(t); 113 return t; 114 } 115 116 int find(int t,int k) 117 { 118 down(t); 119 if (k==size[c[t][0]]+1) return t; 120 if (k<size[c[t][0]]+1) return find(c[t][0],k); 121 if (k>size[c[t][0]]+1) return find(c[t][1],k-size[c[t][0]]-1); 122 } 123 124 void del(int &x) 125 { 126 if (!x) return; 127 q[++tail]=x; 128 fa[x]=0; 129 del(c[x][0]); 130 del(c[x][1]); 131 la[x]=ra[x]=ma[x]=-inf; 132 x=0; 133 } 134 135 int main() 136 { 137 //freopen("build.in","r",stdin); 138 //freopen("build.out","w",stdout); 139 scanf("%d %d",&n,&m); 140 for (int i=2;i<=n+1;i++) 141 { 142 scanf("%d",&a[i]); 143 } 144 a[st=1]=0; a[ed=n+2]=0; 145 ra[0]=la[0]=ma[0]=-inf; 146 rot=build(1,n+2); 147 char sign[20]; 148 int x,y,l,r,z,ans; 149 for (int i=1;i<=m;i++) 150 { 151 scanf("%s",&sign); 152 if (sign[0]=='I') 153 { 154 scanf("%d %d",&x,&y); 155 l=find(rot,x+1); r=find(rot,x+2); 156 splay(r,rot); splay(l,c[rot][0]); 157 for (int j=1;j<=y;j++) 158 scanf("%d",&a[j]); 159 int tmp=build(1,y); 160 fa[tmp]=l; c[l][1]=tmp; 161 update(l); update(r); 162 } 163 if (sign[0]=='D') 164 { 165 scanf("%d %d",&x,&y); 166 l=find(rot,x); r=find(rot,x+y+1); 167 splay(r,rot); splay(l,c[rot][0]); 168 del(c[l][1]); 169 update(l); update(r); 170 } 171 if (sign[0]=='M'&&sign[2]=='K') 172 { 173 scanf("%d %d %d",&x,&y,&z); 174 l=find(rot,x); r=find(rot,x+y+1); 175 splay(r,rot); splay(l,c[rot][0]); 176 recover(c[l][1],z); 177 } 178 if (sign[0]=='R') 179 { 180 scanf("%d %d",&x,&y); 181 l=find(rot,x); r=find(rot,x+y+1); 182 splay(r,rot); splay(l,c[rot][0]); 183 reverse(c[l][1]); 184 } 185 if (sign[0]=='G') 186 { 187 scanf("%d %d",&x,&y); 188 l=find(rot,x); r=find(rot,x+y+1); 189 splay(r,rot); splay(l,c[rot][0]); 190 ans=sum[c[l][1]]; 191 printf("%d\n",ans); 192 } 193 if (sign[0]=='M'&&sign[2]=='X') 194 { 195 splay(ed,rot); splay(st,c[rot][0]); 196 ans=ma[c[st][1]]; 197 printf("%d\n",ans); 198 } 199 //for(int i=1;i<=num;i++) cout<<find(rot,i)<<' ';cout<<"\n"; 200 //for (int i=1;i<=num;i++) cout<<i<<' '<<size[i]<<' '<<fa[i]<<' '<<c[i][0]<<' '<<c[i][1]<<' '<<la[i]<<' '<<ra[i]<<' '<<ma[i]<<' '<<sum[i]<<endl; 201 } 202 return 0; 203 }
AC without art, no better than WA !