记录编号 | 227844 | 评测结果 | AAAAAAAAAA | ||
---|---|---|---|---|---|
题目名称 | [NOI 2005]维护数列 | 最终得分 | 100 | ||
用户昵称 | 是否通过 | 通过 | |||
代码语言 | C++ | 运行时间 | 6.169 s | ||
提交时间 | 2016-02-18 21:14:56 | 内存使用 | 35.35 MiB | ||
#include<cstdio> #include<iostream> #include<queue> using namespace std; const int SIZEN=1000010; const int INF=0x7fffffff/8; int N,M; int a[SIZEN],id[SIZEN],root,cnt; int sum[SIZEN];//以i为根的子树权值之和 int siz[SIZEN];//以i为根的子树节点个数 int mx[SIZEN];//以i为根的子树权值最大的区间和 int lx[SIZEN],rx[SIZEN];//辅助数组,用于求mx[] bool tag[SIZEN];//区间覆盖标记 bool rev[SIZEN];//区间翻转标记 int fa[SIZEN];//父亲 int son[SIZEN][2];//0代表左儿子,1代表右儿子 int v[SIZEN]; queue<int> q; void print(int x)//调试接口 { cout<<x<<endl; cout<<id[x]<<" "<<"v:"<<v[x]<<" "<<"siz:"<<siz[x]<<" "<<"sum:"<<sum[x]<<endl; cout<<"l:"<<son[x][0]<<" "<<"r:"<<son[x][1]<<endl; cout<<endl; } void pushdown(int rt) { int l=son[rt][0],r=son[rt][1]; if(tag[rt]) { rev[rt]=tag[rt]=0; if(l) tag[l]=1,v[l]=v[rt],sum[l]=v[rt]*siz[l]; if(r) tag[r]=1,v[r]=v[rt],sum[r]=v[rt]*siz[r]; if(v[rt]>=0) { if(l) mx[l]=lx[l]=rx[l]=sum[l]; if(r) mx[r]=lx[r]=rx[r]=sum[r]; } else { if(l) lx[l]=rx[l]=0,mx[l]=v[rt]; if(r) lx[r]=rx[r]=0,mx[r]=v[rt]; } } if(rev[rt]) { rev[rt]^=1;rev[l]^=1;rev[r]^=1; swap(lx[l],rx[l]);swap(lx[r],rx[r]); swap(son[l][0],son[l][1]);swap(son[r][0],son[r][1]); } } void sl_print(int x) { pushdown(x); int l=son[x][0],r=son[x][1]; if(l)sl_print(l); cout<<v[x]<<" "; if(r)sl_print(r); } void read() { scanf("%d%d",&N,&M); for(int i=1;i<=N;i++) scanf("%d",&a[i+1]); mx[0]=a[1]=a[N+2]=-INF; for(int i=1;i<=N+2;i++) id[i]=i; } void update(int x) { int ls=son[x][0],rs=son[x][1]; sum[x]=sum[ls]+sum[rs]+v[x]; siz[x]=siz[ls]+siz[rs]+1; mx[x]=max(mx[ls],mx[rs]); mx[x]=max(mx[x],rx[ls]+lx[rs]+v[x]); lx[x]=max(lx[ls],sum[ls]+v[x]+lx[rs]); rx[x]=max(rx[rs],sum[rs]+v[x]+rx[ls]); } void rotate(int x,int &k) { int y=fa[x],z=fa[y],l,r; if(son[y][1]==x) l=1; else l=0; r=l^1; if(y==k) k=x; else { if(son[z][0]==y) son[z][0]=x; else son[z][1]=x; } fa[son[x][r]]=y;fa[y]=x;fa[x]=z; son[y][l]=son[x][r];son[x][r]=y; update(y);update(x); } void splay(int x,int &k) { while(x!=k) { int y=fa[x],z=fa[y]; if(y!=k)//y==k时,z=0; { if(son[y][0]==x^son[z][0]==y) rotate(x,k); else rotate(y,k); } rotate(x,k); } } int find(int rt,int k)//找到k在二叉搜索树中的位置 { pushdown(rt); int l=son[rt][0],r=son[rt][1]; if(siz[l]+1==k) return rt; if(siz[l]>=k) return find(l,k); else return find(r,k-siz[l]-1); } int spilt(int pos,int tot)//把pos之后的tot个元素旋转到一棵子树中,并返回子树的根节点 { int x=find(root,pos),y=find(root,pos+tot+1); splay(x,root);splay(y,son[x][1]); return son[y][0]; } void rec(int x)//删除x这颗子树 { if(!x) return; int l=son[x][0],r=son[x][1]; rec(l);rec(r);q.push(x); fa[x]=son[x][0]=son[x][1]=0; tag[x]=rev[x]=0; } void built(int l,int r,int f)//将区间l~r建造一棵中序遍历树 { if(l>r) return; int mid=(l+r)>>1,now=id[mid],last=id[f]; if(l==r) { sum[now]=a[l];siz[now]=1; tag[now]=rev[now]=0; if(a[l]>=0) lx[now]=rx[now]=mx[now]=a[l]; else lx[now]=rx[now]=0,mx[now]=a[l]; } else built(l,mid-1,mid),built(mid+1,r,mid); v[now]=a[mid];fa[now]=last;update(now); if(mid>=f) son[last][1]=now; else son[last][0]=now; } void insert(int pos,int tot)//插入操作 { for(int i=1;i<=tot;i++) scanf("%d",&a[i]); for(int i=1;i<=tot;i++) { if(!q.empty()) id[i]=q.front(),q.pop(); else id[i]=++cnt; } built(1,tot,0);int z=id[(1+tot)>>1]; int x=find(root,pos+1),y=find(root,pos+2); splay(x,root);splay(y,son[x][1]); fa[z]=y;son[y][0]=z; update(y),update(x); } void erase(int pos,int tot)//删除操作 { int x=spilt(pos,tot),y=fa[x]; rec(x);son[y][0]=0; update(y);update(fa[y]); } void SAME(int pos,int tot,int val)//区间赋值 { int x=spilt(pos,tot),y=fa[x]; v[x]=val;tag[x]=1;sum[x]=siz[x]*val; if(val>=0) lx[x]=rx[x]=mx[x]=sum[x]; else lx[x]=rx[x]=0,mx[x]=val; update(y);update(fa[y]); } void getsum(int pos,int tot)//区间求和 { int x=spilt(pos,tot); printf("%d\n",sum[x]); } void rever(int pos,int tot)//区间翻转 { int x=spilt(pos,tot),y=fa[x]; if(!tag[x]) { rev[x]^=1; swap(son[x][1],son[x][0]); swap(lx[x],rx[x]); update(y);update(fa[y]); } } void prepare() { root=(N+3)>>1;cnt=N+2; built(1,N+2,0); } void work() { char ch[10]; int pos,tot,c; for(int i=1;i<=M;i++) { scanf("%s",ch); if(ch[0]!='M'||ch[2]!='X') scanf("%d%d",&pos,&tot); if(ch[0]=='I') insert(pos,tot); if(ch[0]=='D') erase(pos,tot); if(ch[0]=='M') { if(ch[2]=='X') printf("%d\n",mx[root]); else { scanf("%d",&c); SAME(pos,tot,c); } } if(ch[0]=='G') getsum(pos,tot); if(ch[0]=='R') rever(pos,tot); } } int main() { freopen("seq2005.in","r",stdin); freopen("seq2005.out","w",stdout); read(); prepare(); work(); return 0; }