首页 > 代码库 > [NOI2005]维修数列

[NOI2005]维修数列

技术分享

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

Sample Output

-1
10
1
10
题解:
splay,几乎所有模式都在里面
注意这个splay维护的是位置
插入:将第pos旋到根,第pos+1(名次树操作)旋到根的右子树
这里的插入用了一种二分的方法,可以保证有序,且可以直接反转
删除:将第pos旋到根,第pos+tot+1旋到根的右子树
如果用了内存池还要递归回收(详见erase)
反转:留下反转标记,每次直接交换左右节点
修改同上,注意0
求和直接维护
求最大子序列和有点复杂,维护节点最大子序列和,右端最大和,左端最大和,详见(pushdown)
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int MAXN=500010;
  7 int tot2,tot1,s[MAXN],pre[MAXN],ch[MAXN][2],key[MAXN],sum[MAXN],maxsum[MAXN],lx[MAXN],rx[MAXN],a[MAXN];
  8 int size[MAXN],same[MAXN],root,n,m;
  9 bool rev[MAXN];
 10 int gi()
 11 {
 12     char ch=getchar();int s=0;int sign=1;
 13     while (ch<0||ch>9)
 14     {if (ch==-) sign=-1;ch=getchar();}
 15     while (ch>=0&&ch<=9)
 16     {s=s*10+ch-0;ch=getchar();}
 17 return s*sign;
 18 }
 19 void NewNode(int &r,int fa,int k)
 20 {
 21     if (tot2) r=s[tot2--];
 22     else
 23         r=++tot1;
 24     pre[r]=fa;
 25     ch[r][0]=ch[r][1]=0;
 26     key[r]=k;
 27     sum[r]=k;
 28     rev[r]=same[r]=0;
 29     lx[r]=rx[r]=maxsum[r]=k;
 30     size[r]=1;
 31 }
 32 void pushup(int x)
 33 {
 34     int lson=ch[x][0],rson=ch[x][1];
 35     size[x]=size[lson]+size[rson]+1;
 36     sum[x]=sum[lson]+sum[rson]+key[x];
 37     lx[x]=max(lx[lson],sum[lson]+key[x]+max(0,lx[rson]));
 38     rx[x]=max(rx[rson],sum[rson]+key[x]+max(0,rx[lson]));
 39     maxsum[x]=max(0,rx[lson])+key[x]+max(0,lx[rson]);
 40     maxsum[x]=max(maxsum[lson],max(maxsum[x],maxsum[rson]));
 41 }
 42 void update_same(int x,int c);
 43 void update_Reverse(int x);
 44 void pushdown(int x)
 45 {
 46     if (same[x])
 47     {
 48         update_same(ch[x][0],key[x]);
 49         update_same(ch[x][1],key[x]);
 50         same[x]=0;
 51     }
 52     if (rev[x])
 53     {
 54         update_Reverse(ch[x][0]);
 55         update_Reverse(ch[x][1]);
 56         rev[x]=0;
 57     }
 58 }
 59 void build(int &x,int l,int r,int fa)
 60 {
 61     if (l>r) return;
 62     int mid=(l+r)/2;
 63     NewNode(x,fa,a[mid]);
 64     build(ch[x][0],l,mid-1,x);
 65     build(ch[x][1],mid+1,r,x);
 66     pushup(x);
 67 }
 68 int getkth(int r,int k)
 69 {
 70     pushdown(r);
 71     int x=size[ch[r][0]]+1;
 72     if (k==x) return r;
 73     if (k<x) getkth(ch[r][0],k);
 74     else getkth(ch[r][1],k-x);
 75 }
 76 void rotate(int x,bool t)
 77 {
 78     int y=pre[x];
 79     pushdown(y);pushdown(x);
 80     ch[y][!t]=ch[x][t];
 81     pre[ch[x][t]]=y;
 82     if (pre[y])
 83       ch[pre[y]][ch[pre[y]][1]==y]=x;
 84       pre[x]=pre[y];
 85       ch[x][t]=y;
 86       pre[y]=x;
 87     pushup(y);
 88 }
 89 void splay(int x,int goal)
 90 {
 91     pushdown(x);
 92     while (pre[x]!=goal)
 93     {
 94         if (pre[pre[x]]==goal)
 95         {
 96             pushdown(pre[x]);
 97             pushdown(x);
 98             rotate(x,ch[pre[x]][0]==x);
 99         }
100         else
101         {
102             pushdown(pre[pre[x]]);
103             pushdown(pre[x]);
104             pushdown(x);
105             int y=pre[x],kind=ch[pre[y]][0]==y;
106             if (ch[y][kind]==x)
107             {
108                 rotate(x,!kind);
109                 rotate(x,kind);
110             }
111             else
112             {
113                 rotate(y,kind);
114                 rotate(x,kind);
115             }
116         }
117     }
118     pushup(x);
119     if (goal==0) root=x;
120 }
121 void insert(int pos,int tot)
122 {int i;
123     for (i=1; i<=tot; i++)
124     {
125         a[i]=gi();
126     }
127     splay(getkth(root,pos+1),0);
128     splay(getkth(root,pos+2),root);
129     build(ch[ch[root][1]][0],1,tot,ch[root][1]);
130     pushup(ch[root][1]);
131     pushup(root);
132 }
133 void erase(int r)
134 {
135     if (!r) return ;
136     s[++tot2]=r;
137     erase(ch[r][0]);
138     erase(ch[r][1]);
139 }
140 void Delete(int pos,int tot)
141 {
142     splay(getkth(root,pos),0);
143     splay(getkth(root,pos+tot+1),root);
144     erase(ch[ch[root][1]][0]);
145     pre[ch[ch[root][1]][0]]=0;
146     ch[ch[root][1]][0]=0;
147     pushup(ch[root][1]);
148     pushup(root);
149 }
150 void update_same(int x,int c)
151 {
152     if (!x) return;
153     key[x]=c;
154     sum[x]=size[x]*c;
155     lx[x]=rx[x]=maxsum[x]=max(c,size[x]*c);
156     same[x]=1;
157 }
158 void Make_same(int pos,int tot,int c)
159 {
160     splay(getkth(root,pos),0);
161     splay(getkth(root,pos+tot+1),root);
162     update_same(ch[ch[root][1]][0],c);
163     pushup(ch[root][1]);
164     pushup(root);
165 }
166 void update_Reverse(int x)
167 {
168     if (!x) return;
169     swap(ch[x][0],ch[x][1]);
170     swap(lx[x],rx[x]);
171     rev[x]^=1;
172 }
173 void Reverse(int pos,int tot)
174 {
175     splay(getkth(root,pos),0);
176     splay(getkth(root,pos+tot+1),root);
177     update_Reverse(ch[ch[root][1]][0]);
178     pushup(ch[root][1]);
179     pushup(root);
180 }
181 int getsum(int pos,int tot)
182 {
183     splay(getkth(root,pos),0);
184     splay(getkth(root,pos+tot+1),root);
185     return sum[ch[ch[root][1]][0]];
186 }
187 int Max_sum()
188 {
189     splay(getkth(root,1),0);
190     splay(getkth(root,size[root]),root);
191     return maxsum[ch[ch[root][1]][0]];
192 }
193 int main()
194 {int i,j,x,y,z;
195  char str[101];
196     cin>>n>>m;
197     for (i=1; i<=n; i++)
198     {
199         a[i]=gi();
200     }
201     lx[root]=rx[root]=maxsum[root]=-2e9;
202     NewNode(root,0,-1);
203     NewNode(ch[root][1],root,-1);
204     build(ch[ch[root][1]][0],1,n,ch[root][1]);
205     pushup(ch[root][1]);
206     pushup(root);
207     for (i=1; i<=m; i++)
208     {
209         scanf("%s",str);
210         if (str[0]==I)
211         {
212             x=gi();y=gi();
213             insert(x,y);
214         }
215         else if (str[0]==D)
216         {
217             x=gi();y=gi();
218             Delete(x,y);
219         }
220         else if (str[0]==M&&str[4]==-)
221         {
222             x=gi();y=gi();z=gi();
223             Make_same(x,y,z);
224         }
225         else if (str[0]==R)
226         {
227             x=gi();
228             y=gi();
229             Reverse(x,y);
230         }
231         else if (str[0]==G)
232         {
233             x=gi();
234             y=gi();
235             printf("%d\n",getsum(x,y));
236         }
237         else if (str[0]==M&&str[3]==-)
238         {
239             printf("%d\n",Max_sum());
240         }
241     }
242 }

 

[NOI2005]维修数列