【NOI2005】 维护数列
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
维护数列 【问题描述】 请写一个程序,要求维护一个数列,支持以下 6 种操作: (请注意,格式栏中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1. 插入 INSERT_posi_tot_c1_c2_..._ctot 在当前数列的第 posi 个数字后插入 tot个数字:c1, c2, ..., ctot; 若在数列首插入,则 posi 为 0 从当前数列的第 posi 个数字开始连续 2. 删除 DELETE_posi_tot 从当前数列的第 posi 个数字开始连续删除 tot 个数字 3. 修改 MAKE-SAME_posi_tot_c 将当前数列的第 posi 个数字开始的连续 tot 个数字统一修改为 c 4. 翻转 REVERSE_posi_tot 取出从当前数列的第 posi 个数字开始的 tot 个数字,翻转后放入原来的位置 5. 求和 GET-SUM_posi_tot 计算从当前数列开始的第 posi 个数字开始的 tot 个数字的和并输出 6. 求和最大的子列 MAX-SUM 求出当前数列中和最大的一段子列,并输出最大和 【输入格式】 输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目。 第 2 行包含 N 个数字,描述初始时的数列。 以下 M 行,每行一条命令,格式参见问题描述中的表格。 【输出格式】 对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结 果,每个答案(数字)占一行。 【输入样例】 98 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 【输出样例】 -1 10 1 10 【样例说明】 初始时,我们拥有数列 2 -6 3 5 1 -5 -3 6 3 执行操作 GET-SUM 5 4, 表示求出数列中从第 5 个数开始连续 4 个数字之和, 如下图中的灰色部分 1+(-5)+(-3)+6 = -1: 2 -6 3 5 1 -5 -3 6 3 执行操作 MAX-SUM,表示要求求出当前数列中最大的一段和,即如下图所 示,应为 3+5+1+(-5)+(-3)+6+3 = 10: 2 -6 3 5 1 -5 -3 6 3 执行操作 INSERT 8 3 -5 7 2,即在数列中第 8 个数字后插入-5 7 2,如下所示 的灰色部分: 2 -6 3 5 1 -5 -3 6 -5 7 2 3 执行操作 DELETE 12 1,表示删除第 12 个数字,即最后一个: 2 -6 3 5 1 -5 -3 6 -5 7 2 执行操作 MAKE-SAME 3 3 2,表示从第 3 个数开始的 3 个数字,即下图中 的灰色部分,统一修改为 2: 2 -6 3 5 1 -5 -3 6 -5 7 2 2 -6 2 2 2 -5 -3 6 -5 7 2 改为 执行操作 REVERSE 3 6,表示取出数列中从第 3 个数开始的连续 6 个数: 2 -6 2 2 2 -5 -3 6 -5 7 2 如上所示的灰色部分 2 2 2 -5 -3 6, 翻转后得到 6 -3 -5 2 2 2, 并放回原来位置: 2 -6 6 -3 -5 2 2 2 -5 7 2 最后执行 GET-SUM 5 4 和 MAX-SUM,不难得到答案 1 和 10。 GET-SUM 5 4 2 -6 6 -3 -5 2 2 2 -5 7 2 MAX-SUM 【评分方法】 本题设有部分分,对于每一个测试点: l 如果你的程序能在输出文件正确的位置上打印 GET-SUM 操作的答案, 你可以得到该测试点 60%的分数; l 如果你的程序能在输出文件正确的位置上打印 MAX-SUM 操作的答案, 你可以得到该测试点 40%的分数; l 以上两条的分数可以叠加,即如果你的程序正确输出所有 GET-SUM 和 MAX-SUM 操作的答案,你可以得到该测试点 100%的分数。 请注意:如果你的程序只能正确处理某一种操作,请确定在输出文件正确的 位置上打印结果,即必须为另一种操作留下对应的行,否则我们不保证可以正 确评分。 【数据规模和约定】 你可以认为在任何时刻,数列中至少有 1 个数。 输入数据一定是正确的,即指定位置的数在数列中一定存在。 50%的数据中,任何时刻数列中最多含有 30 000 个数; 100%的数据中,任何时刻数列中最多含有 500 000 个数。 100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。 100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件 大小不超过 20MBytes。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 (* 2 *Problem: NOI2007 维护数列 3 *Author : Chen Yang 4 *Time : 2012.6.4 11:00 am 5 *State : Solved 6 *Memo : splay替代块状数组 7 *) 8 program sequence; 9 const maxn=500010; 10 maxc=11000; 11 var 12 n,m,i,j,k,root,x,posi,t,head:longint; 13 p:char; 14 op:array[0..maxn] of boolean; 15 l,r,a,next,c,best,s,lm,rm,sum:array[0..maxn] of longint; 16 //==================== 17 function max(a,b:longint):longint; inline; 18 begin if a>b then exit(a) else exit(b); end; 19 //==================== 20 procedure updata(k:longint); inline; 21 var ls,rs:longint; 22 begin 23 ls:=l[k]; rs:=r[k]; 24 sum[k]:=sum[ls]+sum[rs]+a[k]; 25 lm[k]:=max(lm[ls],sum[ls]+lm[rs]+a[k]); 26 rm[k]:=max(rm[rs],sum[rs]+rm[ls]+a[k]); 27 best[k]:=max(max(best[ls],best[rs]),rm[ls]+lm[rs]+a[k]); 28 s[k]:=s[ls]+s[rs]+1; 29 end; 30 //==================== 31 procedure l_rotate(var k:longint); inline; 32 var y:longint; 33 begin 34 y:=r[k]; r[k]:=l[y]; l[y]:=k; 35 updata(k); k:=y; 36 end; 37 //==================== 38 procedure r_rotate(var k:longint); inline; 39 var y:longint; 40 begin 41 y:=l[k]; l[k]:=r[y]; r[y]:=k; 42 updata(k); k:=y; 43 end; 44 //==================== 45 procedure put(k,cc:longint; oppo:boolean); inline; 46 var y:longint; 47 begin 48 if k=0 then exit; 49 if oppo then 50 begin 51 y:=l[k]; l[k]:=r[k]; r[k]:=y; 52 y:=lm[k]; lm[k]:=rm[k]; rm[k]:=y; 53 op[k]:=not op[k]; 54 end; 55 if cc<1001 then 56 begin 57 c[k]:=cc; a[k]:=cc; sum[k]:=s[k]*cc; 58 best[k]:=max(0,sum[k]); 59 lm[k]:=best[k]; rm[k]:=best[k]; 60 if best[k]=0 then best[k]:=cc; 61 end; 62 end; 63 //==================== 64 procedure splay(var k:longint; t:longint); 65 var y:longint; 66 begin 67 put(l[k],c[k],op[k]); put(r[k],c[k],op[k]); 68 op[k]:=false; c[k]:=maxc; y:=s[l[k]]+1; 69 if t=y then exit else 70 if t>y then 71 begin 72 splay(r[k],t-y); l_rotate(k); 73 end else begin 74 splay(l[k],t); r_rotate(k); 75 end; 76 end; 77 //==================== 78 procedure built(var k:longint; lx,rx:longint); 79 begin 80 if lx>rx then exit; 81 k:=(lx+rx)>>1; 82 built(l[k],lx,k-1); 83 built(r[k],k+1,rx); 84 updata(k); 85 end; 86 //==================== 87 procedure release(k:longint); 88 begin 89 if k=0 then exit; 90 next[k]:=head; head:=k; 91 release(l[k]); release(r[k]); 92 end; 93 //==================== 94 begin 95 assign(input,'sequence.in'); reset(input); 96 assign(output,'sequence.out'); rewrite(output); 97 read(n,m); root:=0; 98 fillchar(c,sizeof(c),1); 99 a[1]:=-10000; a[n+2]:=-10000; best[0]:=-10000; 100 for i:=2 to n+1 do read(a[i]); readln; 101 head:=n+3; 102 for i:=head+1 to maxn do next[i-1]:=i; 103 built(root,1,n+2); 104 for m:=1 to m do 105 begin 106 read(p); 107 case p of 108 'I':begin 109 while p<>' ' do read(p); 110 read(posi,t); splay(root,posi+2); 111 for t:=1 to t do 112 begin 113 read(j); k:=head; head:=next[head]; 114 a[k]:=j; l[k]:=l[root]; l[root]:=k; 115 r[k]:=0; c[k]:=maxc; op[k]:=false; 116 updata(k); 117 end; 118 updata(root); 119 end; 120 'D':begin 121 while p<>' ' do read(p); 122 read(posi,t); 123 splay(root,posi); 124 splay(root,posi+t+1); 125 release(r[l[root]]); r[l[root]]:=0; 126 updata(l[root]); updata(root); 127 end; 128 'M':begin 129 read(p); read(p); 130 case p of 131 'K':begin 132 while p<>' ' do read(p); 133 read(posi,t,x); 134 splay(root,posi); 135 splay(root,posi+t+1); 136 put(r[l[root]],x,false); 137 updata(l[root]); updata(root); 138 end; 139 'X':writeln(best[root]); 140 end; 141 end; 142 'R':begin 143 while p<>' ' do read(p); 144 read(posi,t); 145 splay(root,posi); 146 splay(root,posi+t+1); 147 put(r[l[root]],maxc,true); 148 updata(l[root]); updata(root); 149 end; 150 'G':begin 151 while p<>' ' do read(p); 152 read(posi,t); 153 splay(root,posi); 154 splay(root,posi+t+1); 155 updata(root); 156 writeln(sum[r[l[root]]]); 157 end; 158 end; 159 readln; 160 end; 161 close(input); close(output); 162 end.
(下面这个主模块忘加return 0了。。虽然这道题没有影响,但还是要注意。。。)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 *Problem: NOI2007 维护数列 3 *Author : Chen Yang 4 *Time : 2012.6.4 3:00 pm 5 *State : Solved 6 *Memo : splay替代块状数组 7 */ 8 #include <cstdio> 9 #include <cstdlib> 10 #include <cstring> 11 #include <string> 12 #include <algorithm> 13 using namespace std; 14 const int maxn = 500010, maxc = 10000; 15 int n, m, a[maxn], next[maxn], head; 16 char s[100]; 17 struct tree 18 { 19 int root,l[maxn], r[maxn], s[maxn], sum[maxn]; 20 int best[maxn], lm[maxn], rm[maxn], lazy[maxn]; 21 bool op[maxn]; 22 tree() { memset(lazy, 1, sizeof(lazy)); root = 0; best[0] = -maxc;} 23 void l_rotate(int &k) 24 { int y=r[k]; r[k]=l[y]; l[y]=k; updata(k); k=y; } 25 void r_rotate(int &k) 26 { int y=l[k]; l[k]=r[y]; r[y]=k; updata(k); k=y; } 27 void splay(int &k, int t) 28 { 29 pushlazy(l[k],lazy[k],op[k]); pushlazy(r[k],lazy[k],op[k]); 30 op[k] = 0, lazy[k] = maxc; //! 31 int y = s[l[k]]+1; 32 if (t == y) return; 33 else if (t>y) { splay(r[k],t-y), l_rotate(k); } 34 else { splay(l[k],t), r_rotate(k); } 35 } 36 void release(int k) 37 { 38 if (!k) return; 39 next[k] = head, head = k; 40 release(l[k]), release(r[k]); 41 } 42 void pushlazy(int k, int c, bool oppo) 43 { 44 if (!k) return; 45 if (oppo) 46 { 47 swap(l[k], r[k]); swap(lm[k], rm[k]); 48 op[k] = !op[k]; 49 } 50 if (c < 1001) 51 { 52 lazy[k] = a[k] = c; sum[k] = c*s[k]; 53 best[k] = max(c, sum[k]); 54 lm[k] = rm[k] = max(0, best[k]); 55 } 56 } 57 void updata(int k) 58 { 59 int ls = l[k], rs = r[k]; 60 s[k] = s[ls]+s[rs]+1; 61 sum[k] = sum[ls]+sum[rs]+a[k]; 62 lm[k] = max(lm[ls], sum[ls]+lm[rs]+a[k]); 63 rm[k] = max(rm[rs], sum[rs]+rm[ls]+a[k]); 64 best[k] = max(max(best[ls], best[rs]), rm[ls]+a[k]+lm[rs]); 65 } 66 void built(int &k, int L, int R) 67 { 68 if (L>R) return; 69 k = (L+R) >> 1; 70 built(l[k], L, k-1); built(r[k], k+1, R); 71 updata(k); 72 } 73 void ins() 74 { 75 int p, t; scanf("%d%d", &p, &t); 76 splay(root, p+2); 77 while (t--) 78 { 79 int j; scanf("%d", &j); 80 int k = head; head = next[head]; 81 a[k] = j, lazy[k] = maxc, op[k] = 0; 82 l[k] = l[root], r[k] = 0, l[root] = k; 83 updata(k); 84 } 85 updata(root); 86 } 87 void del() 88 { 89 int p, t; scanf("%d%d", &p, &t); 90 splay(root, p); splay(root, p+t+1); 91 release(r[l[root]]); r[l[root]] = 0; 92 updata(l[root]); updata(root); 93 } 94 void make() 95 { 96 int p, t, c; scanf("%d%d%d", &p, &t, &c); 97 splay(root, p); splay(root, p+t+1); 98 pushlazy(r[l[root]], c, 0); 99 updata(l[root]); updata(root); 100 } 101 void rev() 102 { 103 int p, t; scanf("%d%d", &p, &t); 104 splay(root, p); splay(root, p+t+1); 105 pushlazy(r[l[root]], maxc, 1); 106 updata(l[root]); updata(root); 107 } 108 void get() 109 { 110 int p, t; scanf("%d%d", &p, &t); 111 splay(root, p); splay(root, p+t+1); 112 printf("%d\n", sum[r[l[root]]]); updata(root); 113 } 114 } S; 115 116 int main() 117 { 118 freopen("sequence.in", "r", stdin); 119 freopen("sequence.out", "w", stdout); 120 scanf("%d%d", &n, &m); 121 a[1] = -maxc, a[n+2] = -maxc, head = n+3; 122 for (int i=head+1; i<maxn; ++i) next[i-1] = i; 123 for (int i=2; i<n+2; ++i) scanf("%d", a+i); 124 S.built(S.root, 1, n+2); 125 while (m--) 126 { 127 scanf("%s", s); 128 if (s[0]=='I') S.ins(); else 129 if (s[0]=='D') S.del(); else 130 if (s[0]=='M' && s[2]=='K') S.make(); else 131 if (s[0]=='R') S.rev(); else 132 if (s[0]=='G') S.get(); else 133 if (s[0]=='M' && s[2]=='X') printf("%d\n", S.best[S.root]); 134 } 135 }