bzoj:1500: [NOI2005]维修数列
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj:1500: [NOI2005]维修数列相关的知识,希望对你有一定的参考价值。
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
总算切掉了这SPLAY神题……
主要就是得每次挪个根,把要操作的区间卡成一颗完整的子树就好啦!
细节还是调了挺久…= =…没办法,弱嘛...>_<
一开始以为回收空间会很麻烦,结果还是开个queue把删掉的节点遍历一遍放进去就完了。
#include<queue> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; queue <int> qh; int n,m,l,r,p,ch,a[500000],pos,tot,u,c,f; inline int read(){ p=0;ch=getchar();f=1; while(ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) p=p*10+ch-48,ch=getchar(); return p*f; } struct tree{ int l,r,k,f,s,c,sum,lx,rx,mx; bool bo; tree(){ bo=f=l=r=sum=0; c=1001; } }; inline int max(int a,int b){return a>b?a:b;} inline int min(int a,int b){return a<b?a:b;} struct splay_tree{ int size,root; tree t[500001]; splay_tree(){ size=0;root=0; } inline void update(int p){ t[p].s=t[t[p].l].s+t[t[p].r].s+1; t[p].sum=t[p].k+t[t[p].l].sum+t[t[p].r].sum; t[p].lx=max(t[t[p].l].lx,t[t[p].r].lx+t[t[p].l].sum+t[p].k); t[p].rx=max(t[t[p].r].rx,t[t[p].l].rx+t[t[p].r].sum+t[p].k); t[p].mx=max(max(t[t[p].l].mx,t[t[p].r].mx),t[t[p].l].rx+t[t[p].r].lx+t[p].k); } inline void pd(int x){ if (t[x].bo){ t[t[x].l].bo^=1;t[t[x].r].bo^=1; swap(t[x].l,t[x].r); swap(t[x].lx,t[x].rx); t[x].bo=0; } if (t[x].c!=1001){ t[x].k=t[x].c; t[t[x].l].c=t[t[x].r].c=t[x].c; t[x].sum=t[x].c*t[x].s; if (t[x].c>=0) t[x].lx=t[x].rx=t[x].mx=t[x].sum;else t[x].lx=t[x].rx=0,t[x].mx=t[x].c; t[x].c=1001; } } inline void ler(int &p){ int k=t[p].r; t[k].f=t[p].f; t[p].f=k; t[t[k].l].f=p; t[p].r=t[k].l; t[k].l=p; update(p);update(k); p=k; } inline void rir(int &p){ int k=t[p].l; t[k].f=t[p].f; t[p].f=k; t[t[k].r].f=p; t[p].l=t[k].r; t[k].r=p; update(p);update(k); p=k; } inline void ph(int &p,bool bo){ if (bo) rir(p);else ler(p); } inline bool gc(int p){return t[t[p].f].l==p;} inline void rot(int p){ if (t[p].f==root) ph(root,gc(p));else if (gc(t[p].f)) ph(t[t[t[p].f].f].l,gc(p));else ph(t[t[t[p].f].f].r,gc(p)); } inline void splay(int p,int f){ while(t[p].f!=f){ if (t[t[p].f].f==f) rot(p);else if (gc(t[p].f)==gc(p)) rot(t[p].f),rot(p);else rot(p),rot(p); } } inline void build(int &p,int l,int r){ if (l>r) return; if (!qh.empty()) p=qh.front(),qh.pop();else p=++size; int mid=(l+r)>>1; t[p].k=a[mid]; build(t[p].l,l,mid-1); build(t[p].r,mid+1,r); t[t[p].l].f=t[t[p].r].f=p; if (l==r){ t[p].sum=a[mid]; if (a[mid]>=0) t[p].lx=t[p].rx=a[mid];else t[p].lx=t[p].rx=0; t[p].mx=a[mid]; t[p].s=1; }else update(p); } inline int find(int x,int y){ pd(x); pd(t[x].l);pd(t[x].r);update(x); if (t[t[x].l].s<y-1) return find(t[x].r,y-1-t[t[x].l].s); if (t[t[x].l].s==y-1) return x; return find(t[x].l,y); } inline void in(int x,int n){ u=find(root,x+2);x=find(root,x+1); splay(x,0);splay(u,x); build(t[u].l,1,n); t[t[u].l].f=u; update(u);update(x); } inline void reuse(int x){ if (!x) return; qh.push(x); reuse(t[x].l);reuse(t[x].r); t[x].l=t[x].r=t[x].bo=0;t[x].c=1001; } inline void del(int x,int n){ u=find(root,x);x=find(root,x+n+1); splay(u,0);splay(x,u); reuse(t[x].l); t[x].l=0; update(x);update(u); } inline void change(int x,int n,int c){ u=find(root,x);x=find(root,x+n+1); splay(u,0);splay(x,u); t[t[x].l].c=c; pd(t[x].l); update(x);update(u); } inline void turn(int x,int n){ u=find(root,x);x=find(root,x+n+1); splay(u,0);splay(x,u); t[t[x].l].bo^=1; pd(t[x].l); update(x);update(u); } inline int qu(int x,int n){ u=find(root,x);x=find(root,x+n+1); splay(u,0);splay(x,u); return t[t[x].l].sum; update(x);update(u); } }t; char ss[20]; int main(){ register int i; n=read();m=read(); for (i=1;i<=n;i++) a[i]=read(); a[0]=-1e8;a[n+1]=-1e8; t.build(t.root,0,n+1); while(m--) { scanf("%s",ss); if (ss[0]==‘I‘){ pos=read();tot=read(); for (i=1;i<=tot;i++) a[i]=read(); t.in(pos,tot); }else if (ss[0]==‘D‘) pos=read(),tot=read(),t.del(pos,tot); else if (ss[0]==‘M‘){ if (ss[2]==‘K‘) pos=read(),tot=read(),c=read(),t.change(pos,tot,c); else printf("%d\n",t.t[t.root].mx); }else if (ss[0]==‘R‘) pos=read(),tot=read(),t.turn(pos,tot); else if (ss[0]==‘G‘) pos=read(),tot=read(),printf("%d\n",t.qu(pos,tot)); } }
以上是关于bzoj:1500: [NOI2005]维修数列的主要内容,如果未能解决你的问题,请参考以下文章