您的位置:首页 > 其它

BZOJ 1500: [NOI2005]维修数列

2017-01-31 16:04 288 查看

1500: [NOI2005]维修数列

Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 12880 Solved: 4112
[Submit][Status][Discuss]

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

Sample Output

-1

10

1

10

HINT



Source

分析:

很久之前就写过...但是没写过...QAQ...没想到这道题还是写了一年(怎么又跨年了...

操作什么的其实就是把线段树换成了Splay...

insert:
把posi+1转到root,posi转到左儿子,新插入的作为posi的右儿子
delete:
把posi+tot转到root,posi-1转到左儿子,删掉posi-1的右儿子
make_same:
把posi+tot转到root,posi-1转到左儿子,posi-1的右儿子修改
reverse:
转法和上面一样,打标记
get_sum:
同上
max_sum:
每个节点维护lsum,rsum,msum

比较麻烦的就是一些边界问题...Zig_Zag的code可以完美滴处理这些问题,然而我只会特判...向Zig_Zag神犇学习...

代码:

其实我的代码还是有缺陷的...只不过可以过掉BZOJ的数据...

正确的写法应该是Zig_Zag那样的...如果把我的code的每次操作完的那两次旋转去掉是过不了的...

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
#define inf 0x3f3f3f3f
using namespace std;

const int maxn=1000000+5;

int tail,stk[maxn];
int n,m,now,tot,root,w[maxn],no[maxn],ls[maxn],rs[maxn],fa[maxn],siz[maxn],sum[maxn],rev[maxn],lmax[maxn],rmax[maxn],mmax[maxn],lazy[maxn];

char opt[13];

inline void reverse(int x){
if(x==0)
return;
swap(ls[x],rs[x]);
swap(lmax[x],rmax[x]);
}

inline void make_same(int x,int y){
if(x==0)
return;
w[x]=y;sum[x]=siz[x]*y;
lmax[x]=rmax[x]=mmax[x]=max(y,sum[x]);//bu neng wei kong
}

inline void push_down(int x){
if(x==0)
return;
if(rev[x])
reverse(ls[x]),reverse(rs[x]),rev[ls[x]]^=1,rev[rs[x]]^=1,rev[x]=0;
if(lazy[x]!=-inf)
make_same(ls[x],lazy[x]),make_same(rs[x],lazy[x]),lazy[ls[x]]=lazy[rs[x]]=lazy[x],lazy[x]=-inf;
}

inline void update(int x){
if(x==0)
return;
lmax[x]=max(lmax[ls[x]],sum[ls[x]]+w[x]+max(0,lmax[rs[x]]));
rmax[x]=max(rmax[rs[x]],sum[rs[x]]+w[x]+max(0,rmax[ls[x]]));
mmax[x]=max(max(mmax[ls[x]],mmax[rs[x]]),w[x]+max(0,rmax[ls[x]])+max(0,lmax[rs[x]]));
sum [x]=sum[ls[x]]+sum[rs[x]]+w[x];
siz [x]=siz[ls[x]]+siz[rs[x]]+1;
}

inline void zig(int x){
int y=fa[x];
update(x);update(y);
if(rs[x])
ls[y]=rs[x],fa[rs[x]]=y;
else
ls[y]=0;
fa[x]=fa[y];
if(fa[x]){
if(ls[fa[y]]==y)
ls[fa[y]]=x;
else
rs[fa[y]]=x;
}
fa[y]=x,rs[x]=y;
update(y),update(x);
}

inline void zag(int x){
int y=fa[x];
update(x);update(y);
if(ls[x])
rs[y]=ls[x],fa[ls[x]]=y;
else
rs[y]=0;
fa[x]=fa[y];
if(fa[x]){
if(ls[fa[y]]==y)
ls[fa[y]]=x;
else
rs[fa[y]]=x;
}
fa[y]=x,ls[x]=y;
update(y),update(x);
}

inline void relax(int x,int y){
if(x!=y)
relax(fa[x],y);
push_down(x);
}

inline void splay(int x,int z){
relax(x,z);
while(fa[x]!=z){
int y=fa[x];
if(fa[y]==z){
if(ls[y]==x)
zig(x);
else
zag(x);
}
else{
if(ls[fa[y]]==y){
if(ls[y]==x)
zig(y),zig(x);
else
zag(x),zig(x);
}
else{
if(rs[y]==x)
zag(y),zag(x);
else
zig(x),zag(x);
}
}
}
update(x);
if(!z)
root=x;
else
update(z);
}

inline int get_num(void){
if(tail)
return stk[tail--];
return ++tot;
}

inline int assign(int x){
int tmp=get_num();
rev[tmp]=0;
w[tmp]=no[x];
lazy[tmp]=-inf;
lmax[tmp]=rmax[tmp]=mmax[tmp]=-inf;
return tmp;
}

inline int build(int l,int r){
if(l==r){
int tmp=assign(l);
update(tmp);return tmp;
}
int mid=(l+r)>>1,L=0,R=0,tmp=assign(mid);
if(l<mid)
L=build(l,mid-1);
if(r>mid)
R=build(mid+1,r);
if(L)
ls[tmp]=L,fa[L]=tmp;
if(R)
rs[tmp]=R,fa[R]=tmp;
update(tmp);
return tmp;
}

inline void del(int x){
if(x==0)
return;
stk[++tail]=x;
fa[x]=rev[x]=0;lazy[x]=-inf;
lmax[x]=rmax[x]=mmax[x]=-inf;
if(ls[x])
del(ls[x]);
if(rs[x])
del(rs[x]);
ls[x]=rs[x]=0;
}

inline int find(int rt,int x){
push_down(rt);
if(siz[ls[rt]]+1==x)
return rt;
else if(siz[ls[rt]]+1>x)
return find(ls[rt],x);
else
return find(rs[rt],x-siz[ls[rt]]-1);
}

inline int read(void){
char ch=getchar();int x=0,f=1;
while(!(ch>='0'&&ch<='9')){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
x=x*10+ch-'0',ch=getchar();
return f*x;
}

signed main(void){
memset(ls,0,sizeof(ls));
memset(rs,0,sizeof(rs));
memset(fa,0,sizeof(fa));
memset(rev,0,sizeof(rev));
memset(sum,0,sizeof(sum));
memset(siz,0,sizeof(siz));
memset(lmax,-inf,sizeof(lmax));
memset(rmax,-inf,sizeof(rmax));
memset(mmax,-inf,sizeof(mmax));
memset(lazy,-inf,sizeof(lazy));
tot=tail=0;
n=read(),m=read();now=n;
for(int i=1;i<=n;i++)
no[i]=read();
root=build(1,n);int pos,tot,x;
while(m--){
scanf("%s",opt);
if(opt[0]=='I'){
pos=read(),tot=read();
for(int i=1;i<=tot;i++)
no[i]=read();
int tmproot=build(1,tot);
if(now==0)
root=tmproot;
else if(pos==0)
splay(find(root,pos+1),0),ls[root]=tmproot,fa[tmproot]=root,update(root);
else if(pos==now)
splay(find(root,pos),0),rs[root]=tmproot,fa[tmproot]=root,update(root);
else
splay(find(root,pos+1),0),splay(find(root,pos),root),rs[ls[root]]=tmproot,fa[tmproot]=ls[root],update(ls[root]),update(root);
now+=tot;
}
else if(opt[0]=='D'){
pos=read(),tot=read();
if(pos==1&&pos+tot-1==now)
root=0;
else if(pos==1)
splay(find(root,pos+tot),0),del(ls[root]),ls[root]=0,update(root);
else if(pos+tot-1==now)
splay(find(root,pos-1),0),del(rs[root]),rs[root]=0,update(root);
else
splay(find(root,pos+tot),0),splay(find(root,pos-1),root),del(rs[ls[root]]),rs[ls[root]]=0,update(ls[root]),update(root);
now-=tot;
}
else if(opt[0]=='M'&&opt[2]=='K'){
pos=read(),tot=read(),x=read();
if(pos==1&&pos+tot-1==now)
make_same(root,x),lazy[root]=x;
else if(pos==1)
splay(find(root,pos+tot),0),make_same(ls[root],x),lazy[ls[root]]=x;
else if(pos+tot-1==now)
splay(find(root,pos-1),0),make_same(rs[root],x),lazy[rs[root]]=x;
else
splay(find(root,pos+tot),0),splay(find(root,pos-1),root),make_same(rs[ls[root]],x),lazy[rs[ls[root]]]=x;
}
else if(opt[0]=='R'){
pos=read(),tot=read();
if(pos==1&&pos+tot-1==now)
reverse(root),rev[root]^=1;
else if(pos==1)
splay(find(root,pos+tot),0),reverse(ls[root]),rev[ls[root]]^=1;
else if(pos+tot-1==now)
splay(find(root,pos-1),0),reverse(rs[root]),rev[rs[root]]^=1;
else
splay(find(root,pos+tot),0),splay(find(root,pos-1),root),reverse(rs[ls[root]]),rev[rs[ls[root]]]^=1;
}
else if(opt[0]=='G'){
pos=read(),tot=read();
if(tot==0)
puts("0");
else if(pos==1&&pos+tot-1==now)
splay(find(root,now),0),splay(find(root,1),0),printf("%d\n",sum[root]);
else if(pos==1)
splay(find(root,pos+tot),0),printf("%d\n",sum[ls[root]]);
else if(pos+tot-1==now)
splay(find(root,pos-1),0),printf("%d\n",sum[rs[root]]);
else
splay(find(root,pos+tot),0),splay(find(root,pos-1),root),printf("%d\n",sum[rs[ls[root]]]);
}
else
splay(find(root,now),0),splay(find(root,1),0),printf("%d\n",mmax[root]);
splay(find(root,1),0);splay(find(root,now),0);
}
return 0;
}//Cap ou pas cap. Cap.


  

By NeighThorn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: