洛谷 P2042 维护数列

来源:互联网 发布:gcf软件下载 编辑:程序博客网 时间:2024/06/15 18:53

这题…mdzz。我想打人。


【分析】
六种操作都比较基本…然而拼到一起就很难了呢呵呵。(对我来说很难)

大家直接参考代码吧。注意一点就是要把删除节点的编号存起来,insert的时候用这些节点,要不然会RE RE RE RE RE RE RE RE RE RERE


【代码】

#include<iostream>#include<cstring>#include<cstdio>#define ll long long#define inf 0x3f3f3f3f#define M(a) memset(a,-inf,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=500000;int n,m,sz,opt,root,top;int a[mxn],c[mxn],f[mxn],ch[mxn][2],key[mxn],size[mxn],tag[mxn],rub[mxn];int reverse[mxn],sum[mxn],lmx[mxn],rmx[mxn],mx[mxn];inline int get(int x){    if(ch[f[x]][1]==x) return 1;return 0;}inline void update(int now){    if(!now) return;    size[now]=1;    int l=ch[now][0],r=ch[now][1];    if(l) size[now]+=size[l];    if(r) size[now]+=size[r];    lmx[now]=max(lmx[l],sum[l]+key[now]+max(0,lmx[r]));    rmx[now]=max(rmx[r],sum[r]+key[now]+max(0,rmx[l]));     mx[now]=max(max(mx[l],mx[r]),max(0,rmx[l])+max(0,lmx[r])+key[now]);    sum[now]=sum[l]+sum[r]+key[now];}inline void rev(int x)  {      if (!x) return;      swap(lmx[x],rmx[x]);      swap(ch[x][0],ch[x][1]);      reverse[x]^=1;  } inline void replace(int x,int d)  {      if (!x) return;    key[x]=d,sum[x]=d*size[x];      lmx[x]=rmx[x]=mx[x]=max(d,d*size[x]);      tag[x]=1;  }  inline void pushdown(int x)  {      if(reverse[x])      {          if(ch[x][0]) rev(ch[x][0]);          if(ch[x][1]) rev(ch[x][1]);          reverse[x]=0;      }      if (tag[x])    {          if(ch[x][0]) replace(ch[x][0],key[x]);          if(ch[x][1]) replace(ch[x][1],key[x]);          tag[x]=0;    }  } inline void rotate(int x){    pushdown(x);    int fa=f[x],fafa=f[fa],which=get(x);    ch[fa][which]=ch[x][which^1],f[ch[fa][which]]=fa;    ch[x][which^1]=fa,f[fa]=x;    f[x]=fafa;    if(fafa) ch[fafa][ch[fafa][1]==fa]=x;    update(fa),update(x);}inline void splay(int x,int lastfa){    for(int fa;(fa=f[x])!=lastfa;rotate(x))      if(f[fa]!=lastfa) rotate(get(x)==get(fa)?fa:x);     if(!lastfa) root=x;}inline int build(int fa,int l,int r){    if(l>r) return 0;    int now,mid=l+r>>1;;    if(!top) now=++sz;    else now=rub[top--];    sum[now]=lmx[now]=rmx[now]=mx[now]=key[now]=a[mid],f[now]=fa,size[now]=1;    tag[now]=reverse[now]=0;    ch[now][0]=build(now,l,mid-1);    ch[now][1]=build(now,mid+1,r);    update(now);    return now;}inline int number(int x){    int now=root;    while(1)    {        pushdown(now);        if(ch[now][0] && x<=size[ch[now][0]]) now=ch[now][0];        else        {            if(x==size[ch[now][0]]+1) return now;            x=x-size[ch[now][0]]-1;            now=ch[now][1];pushdown(now);        }    }}inline void del(int x){    if(!x) return;    rub[++top]=x;    if(ch[x][0]) del(ch[x][0]);    if(ch[x][1]) del(ch[x][1]);}int main(){//  freopen("rand.txt","r",stdin);//  freopen("mine.txt","w",stdout);    M(lmx),M(rmx),M(mx);    char str[105];    int i,j,k,x,y,z,w,tot,posi;    scanf("%d%d",&n,&m);    fo(i,2,n+1) scanf("%d",&a[i]);    a[1]=-inf,a[n+2]=-inf;    root=build(0,1,n+2);    while(m--)    {        scanf("%s",str);        if(str[0]=='I')   //区间插入         {            scanf("%d%d",&posi,&tot);posi++;            fo(i,1,tot) scanf("%d",&a[i]);            x=number(posi),y=number(posi+1);            splay(x,0),splay(y,x);            int tmp=build(ch[root][1],1,tot);            ch[ch[root][1]][0]=tmp;            update(ch[ch[root][1]][0]);            update(ch[root][1]),update(root);        }        if(str[0]=='D')   //区间删除         {            scanf("%d%d",&posi,&tot);posi++;            x=number(posi-1),y=number(posi+tot);            splay(x,0),splay(y,x);            del(ch[ch[root][1]][0]);            f[ch[ch[root][1]][0]]=0;ch[ch[root][1]][0]=0;            update(ch[root][1]),update(root);        }        if(str[0]=='M' && str[2]=='K')  //区间修改        {            scanf("%d%d%d",&posi,&tot,&w);posi++;            x=number(posi-1),y=number(posi+tot);            splay(x,0),splay(y,x);            replace(ch[ch[root][1]][0],w);            update(ch[root][1]),update(root);        }        if(str[0]=='R')   //区间翻转         {            scanf("%d%d",&posi,&tot);posi++;            x=number(posi-1),y=number(posi+tot);            splay(x,0),splay(y,x);            int tmp=ch[ch[root][1]][0];            rev(tmp);            update(ch[root][1]),update(root);        }        if(str[0]=='G')  //区间求和         {            scanf("%d%d",&posi,&tot);posi++;            x=number(posi-1),y=number(posi+tot);            splay(x,0),splay(y,x);            pushdown(ch[ch[root][1]][0]);            update(ch[root][1]),update(root);            printf("%d\n",sum[ch[ch[root][1]][0]]);        }        if(str[0]=='M' && str[2]=='X')        {            printf("%d\n",mx[root]);        }    }    return 0;}/*4 31 -1 -5 1 MAX_SUMREVERSE 1 4MAX_SUM*/
0 0
原创粉丝点击