BZOJ1500:[NOI2005]维修数列

1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 14486  Solved: 4723
[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

 

思路{

  为何发现我的蛋碎了..........

  为何发现被维修的不是数列,而是我.........

  关键是最后一个操作!

  设l[x]为以当前节点所代表的区间左端点为起点的序列最大值,

  那么往上传的时候,由于以下标为键值l[x]=Max(l[ls],Sum[ls]+v[x]+l[rs]);

  同理更新r[x],Max[x]为一段区间内最大值,Max[x]在上传的过程中一路更新(很妙啊~~~)

  然后就轻巧地用嘴巴AC~~~~(调得想死.......)

  膜Hzwer的代码咯.

}

 

#include<bits/stdc++.h>
#define RG register
#define il inline 
#define N 1000005
#define rs (ch[x][1])
#define ls (ch[x][0])
using namespace std;
int ch[N][2],fa[N],sum[N],l[N],r[N],sz[N],v[N],Max[N],rt,id[N],a[N],n,m,cnt;bool tag[N],rev[N];
void up(int x){
   sz[x]=sz[ls]+sz[rs]+1;
   sum[x]=sum[rs]+sum[ls]+v[x];
   Max[x]=max(Max[rs],Max[ls]);
   Max[x]=max(Max[x],v[x]+r[ls]+l[rs]);
   l[x]=max(l[ls],sum[ls]+v[x]+l[rs]);
   r[x]=max(r[rs],sum[rs]+v[x]+r[ls]);
}
void down(int x){
  if(tag[x]){
    rev[x]=tag[x]=0;
    if(rs)v[rs]=v[x],sum[rs]=sz[rs]*v[x],tag[rs]=1;
    if(ls)v[ls]=v[x],sum[ls]=sz[ls]*v[x],tag[ls]=1;
    if(v[x]>=0){
      if(ls)l[ls]=r[ls]=Max[ls]=sum[ls];
      if(rs)l[rs]=r[rs]=Max[rs]=sum[rs];
    }else {
      if(ls)l[ls]=r[ls]=0,Max[ls]=v[x];
      if(rs)l[rs]=r[rs]=0,Max[rs]=v[x];
    }
  }if(rev[x])rev[x]^=1,rev[rs]^=1,rev[ls]^=1,swap(rs,ls),swap(l[rs],r[rs]),swap(l[ls],r[ls]);
}
void Rotate(int x,int &k){
  int y=fa[x],z=fa[y],l,r;if(z)down(z);down(y),down(x);
  l=ch[y][1]==x,r=l^1;
  if(y==k)k=x;
  else ch[z][ch[z][1]==y]=x;
  fa[x]=z,fa[y]=x,fa[ch[x][r]]=y;ch[y][l]=ch[x][r];
  ch[x][r]=y;
  up(y),up(x);
}
void Splay(int x,int &k){
  while(x!=k){
    int y=fa[x],z=fa[y];
    if(y!=k){
      if(ch[z][0]==y^ch[y][0]==x)Rotate(x,k);
      else Rotate(y,k);
    }Rotate(x,k);
  }
}queue<int>que;
int find(int x,int rnk){
  down(x);
  if(sz[ls]+1==rnk)return x;
  if(sz[ls]>=rnk)return find(ls,rnk);
  return find(rs,rnk-sz[ls]-1);
}
void clean(int x){
  if(!x)return;
  clean(rs),clean(ls),que.push(x);
  fa[x]=rs=ls=tag[x]=rev[x]=0;
}
int Split(int k,int tot){
  int x=find(rt,k),y=find(rt,k+tot+1);
  Splay(x,rt),Splay(y,ch[x][1]);
  return ch[y][0];
}
void Querysum(int k,int tot){
  int x=Split(k,tot);
  printf("%d\n",sum[x]);
}
void Modify(int k,int tot,int val){
  int x=Split(k,tot),y=fa[x];
  v[x]=val;tag[x]=1;sum[x]=sz[x]*v[x];
  if(val>=0)l[x]=r[x]=Max[x]=sum[x];
  else l[x]=r[x]=0,Max[x]=v[x];
  up(y),up(fa[y]);
}
void rever(int k,int tot){
  int x=Split(k,tot),y=fa[x];
  if(!tag[x]){
    rev[x]^=1;swap(l[x],r[x]);
    up(y),up(fa[y]);
  }
}
void del(int k,int tot){
  int x=Split(k,tot),y=fa[x];
  clean(x);ch[y][0]=0;up(y),up(fa[y]);  
}
#define mid ((L+R)>>1)
void build(int L,int R,int f){
  if(L>R)return;
  int x=id[mid],faa=id[f];
  if(L==R){
    sz[x]=1,sum[x]=a[L];
    tag[x]=0;
    if(a[L]>=0)l[x]=r[x]=Max[x]=a[L];
    else l[x]=r[x]=0,Max[x]=a[L];
  }else build(L,mid-1,mid),build(mid+1,R,mid);
  v[x]=a[mid],fa[x]=faa;up(x);
  ch[faa][f<=mid]=x;
}
void Insert(int k,int tot){
  for(int i=1;i<=tot;++i)scanf("%d",&a[i]);
  for(int i=1;i<=tot;++i)
    if(!que.empty())id[i]=que.front(),que.pop();
    else id[i]=++cnt;
  build(1,tot,0);int z=id[((1+tot)>>1)];
  int x=find(rt,k+1),y=find(rt,k+2);
  Splay(x,rt),Splay(y,ch[x][1]);
  fa[z]=y,ch[y][0]=z,up(y),up(x);
}int k,tot;
int main(){
  scanf("%d%d",&n,&m);Max[0]=a[1]=a[n+2]=-6666666;
  for(int i=1;i<=n;++i)scanf("%d",&a[i+1]);
  for(int i=1;i<=n+2;++i)id[i]=i;
  build(1,n+2,0);rt=(n+3)>>1,cnt=n+2;
  char s[10];
  for(int i=1;i<=m;++i){
    scanf("%s",s);
    if(s[0]=='I'){scanf("%d%d",&k,&tot),Insert(k,tot);}
    if(s[0]=='D'){scanf("%d%d",&k,&tot),del(k,tot);}
    if(s[0]=='M'&&s[2]=='K'){int c;scanf("%d%d%d",&k,&tot,&c),Modify(k,tot,c);}
    if(s[0]=='R'){scanf("%d%d",&k,&tot),rever(k,tot);}
    if(s[0]=='G'){scanf("%d%d",&k,&tot),Querysum(k,tot);}
    if(s[0]=='M'&&s[2]=='X'){printf("%d\n",Max[rt]);}
  }
  return 0;
}

 

  

 

 

posted @ 2017-07-31 10:41  QYP_2002  阅读(239)  评论(3编辑  收藏  举报