Submit: 12469 Solved: 3955
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
Sample Output
-1
10
1
10
10
1
10
HINT
Source
Splay模板题
真·一道题写一天
每个指令都是基本操作,放在一起就迷之难写……
由于空间限制,必须要重复使用del掉的旧结点
几个WA点:
申请新结点时,没有初始化ch[]
序列st,ed编号记录错误,导致MAX-SUM操作转错
pushdown只处理当前层,并把标记传给下层←会WA,非要把下一层也处理掉才行。
pushdown没有判“当前结点为空时直接跳过”
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int INF=1e9; 10 const int mxn=1000100; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 int stk[mxn],top;//回收结点 18 struct node{ 19 int ch[2]; 20 int fa,w,mk; 21 int rx,lx,max; 22 int size,sum; 23 bool rev; 24 }t[mxn]; 25 int a[mxn];//存储数值 26 int cnt=0; 27 int root=0; 28 int n,m,st,ed; 29 void pd_cov(int rt){//区间修改 30 if(!rt)return; 31 t[rt].w=t[rt].mk; 32 t[rt].sum=t[rt].size*t[rt].w; 33 t[rt].lx=t[rt].rx=t[rt].max=max(t[rt].w,t[rt].sum); 34 return; 35 } 36 void pd_rev(int rt){//区间翻转 37 if(!rt)return; 38 t[rt].rev^=1; 39 swap(t[rt].ch[0],t[rt].ch[1]); 40 swap(t[rt].lx,t[rt].rx);//翻转左右连续和 41 return; 42 } 43 void pushdown(int x){ 44 if(!x)return; 45 int lc=t[x].ch[0],rc=t[x].ch[1]; 46 if(t[x].mk!=-INF){ 47 t[lc].mk=t[rc].mk=t[x].mk; 48 pd_cov(lc);pd_cov(rc); 49 t[x].mk=-INF; 50 } 51 if(t[x].rev){ 52 pd_rev(lc);pd_rev(rc); 53 t[x].rev=0; 54 } 55 return; 56 } 57 inline void pushup(int x){ 58 if(!x)return; 59 int lc=t[x].ch[0],rc=t[x].ch[1]; 60 t[x].lx=max(t[lc].lx,t[lc].sum+t[x].w+max(0,t[rc].lx)); 61 t[x].rx=max(t[rc].rx,t[rc].sum+t[x].w+max(0,t[lc].rx)); 62 t[x].sum=t[lc].sum+t[x].w+t[rc].sum; 63 t[x].max=max(max(t[lc].max,t[rc].max),max(t[rc].lx,0)+t[x].w+max(t[lc].rx,0)); 64 t[x].size=t[lc].size+t[rc].size+1; 65 return; 66 } 67 void rotate(int x,int &k){ 68 int y=t[x].fa,z=t[y].fa,lc,rc; 69 if(t[y].ch[0]==x)lc=0;else lc=1; 70 rc=lc^1; 71 if(y==k)k=x; 72 else t[z].ch[t[z].ch[1]==y]=x; 73 t[x].fa=z;t[y].fa=x; t[t[x].ch[rc]].fa=y; 74 t[y].ch[lc]=t[x].ch[rc];t[x].ch[rc]=y; 75 pushup(y); 76 } 77 void relax(int x,int k){if(x!=k)relax(t[x].fa,k);pushdown(x);return;} 78 void Splay(int x,int &k){ 79 relax(x,k); 80 while(x!=k){ 81 int y=t[x].fa,z=t[y].fa; 82 if(y!=k){ 83 if((t[z].ch[0]==y)^(t[y].ch[0]==x))rotate(x,k); 84 else rotate(y,k); 85 } 86 rotate(x,k); 87 } 88 pushup(x); 89 return; 90 } 91 inline void split(int x,int y){ 92 Splay(x,root); 93 Splay(y,t[x].ch[1]); 94 return; 95 } 96 inline int find(int x,int num){//查询序列中第num个数 97 pushdown(x); 98 int lc=t[x].ch[0],rc=t[x].ch[1]; 99 if(t[lc].size>=num)return find(lc,num); 100 if(t[lc].size+1==num)return x; 101 return find(rc,num-t[lc].size-1); 102 } 103 inline int newnode(int x){//申请新结点 104 int rt; 105 if(top)rt=stk[top--];else rt=++cnt; 106 t[rt].w=a[x]; 107 t[rt].lx=t[rt].rx=t[rt].max=-INF; 108 t[rt].rev=0;t[rt].mk=-INF; 109 return rt; 110 } 111 int Build(int l,int r,int fa){ 112 if(l>r)return 0; 113 int mid=(l+r)>>1,lc,rc; 114 int x=newnode(mid); 115 if(l<mid) t[x].ch[0]=Build(l,mid-1,x); 116 else t[x].ch[0]=0; 117 if(r>mid) t[x].ch[1]=Build(mid+1,r,x); 118 else t[x].ch[1]=0; 119 t[x].fa=fa; 120 pushup(x); 121 return x; 122 } 123 void del(int &x){ 124 if(!x)return; 125 stk[++top]=x; 126 t[x].fa=0; 127 del(t[x].ch[0]),del(t[x].ch[1]); 128 x=0; 129 return; 130 } 131 void insert(int pos,int tot){ 132 for(int i=1;i<=tot;i++)a[i]=read(); 133 int tmp=Build(1,tot,0); 134 int x=find(root,pos+1),y=find(root,pos+2); 135 split(x,y); 136 t[y].ch[0]=tmp;t[tmp].fa=y; 137 pushup(y);pushup(x); 138 return; 139 } 140 void msame(int pos,int tot,int c){ 141 int x=find(root,pos),y=find(root,pos+tot+1); 142 split(x,y); 143 t[t[y].ch[0]].mk=c; 144 pd_cov(t[y].ch[0]); 145 pushup(y);pushup(x); 146 return; 147 } 148 void reverse(int pos,int tot){ 149 int x=find(root,pos),y=find(root,pos+tot+1); 150 split(x,y); 151 pd_rev(t[y].ch[0]); 152 pushup(y);pushup(x); 153 return; 154 } 155 void solvedel(int pos,int tot){ 156 int x=find(root,pos),y=find(root,pos+tot+1); 157 split(x,y); 158 del(t[y].ch[0]); 159 pushup(y);pushup(x); 160 return; 161 } 162 inline int getmax(int pos,int tot){ 163 split(st,ed); 164 return t[t[ed].ch[0]].max; 165 } 166 inline int getsum(int pos,int tot){ 167 int x=find(root,pos),y=find(root,pos+tot+1); 168 split(x,y); 169 return t[t[y].ch[0]].sum; 170 } 171 void DEBUG(){ 172 printf("root:%d ",root); 173 for(int i=1;i<=cnt;i++){ 174 printf("id:%d fa:%d lc:%d rc:%d w:%d ",i,t[i].fa,t[i].ch[0],t[i].ch[1],t[i].w); 175 printf(" lx:%d rx:%d mx:%d ",t[i].lx,t[i].rx,t[i].max); 176 printf(" size:%d ",t[i].size); 177 } 178 return; 179 } 180 int main(){ 181 int i,j,x,y,c; 182 n=read();m=read(); 183 for(i=1;i<=n;i++)a[i+1]=read(); 184 st=1;ed=n+2; 185 a[st]=a[ed]=0; 186 t[0].lx=t[0].rx=t[0].max=-INF; 187 root=Build(1,n+2,0); 188 st=find(root,st);ed=find(root,ed);//记录头尾结点的编号 189 char op[15]; 190 while(m--){ 191 scanf("%s",op); 192 switch(op[0]){ 193 case 'I':x=read();y=read();insert(x,y);break; 194 case 'D':{x=read();y=read();solvedel(x,y);break;} 195 case 'M':{ 196 if(op[2]=='K'){x=read();y=read();c=read();msame(x,y,c);} 197 else{printf("%d ",getmax(st,ed));} 198 break; 199 } 200 case 'R':{x=read();y=read();reverse(x,y);break;} 201 case 'G':{x=read();y=read();printf("%d ",getsum(x,y));break;} 202 case 'B':DEBUG();break; 203 } 204 } 205 return 0; 206 }