【NOI2005】 维护数列

题目描述
维护数列
【问题描述】
请写一个程序,要求维护一个数列,支持以下 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,不难得到答案 110。
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。

 

题解

 

splay(psacal)
  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了。。虽然这道题没有影响,但还是要注意。。。)

splay(C++)
  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 }
posted @ 2012-06-04 16:01  datam  阅读(677)  评论(0编辑  收藏  举报