其他分享
首页 > 其他分享> > [NOI2005]维护数列(区间splay)

[NOI2005]维护数列(区间splay)

作者:互联网

[NOI2005]维护数列(luogu)

打这玩意儿真是要了我的老命

Description

请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格)

 

Code

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define TAGNONE 10000001
using namespace std;
const int N=1e6+10;
struct node
{
    int size,rev,ch[2],res,prer,prel,tag,fa,sum,val;
    void clear()
    {
        size=rev=ch[0]=ch[1]=res=prer=prel=fa=sum=val=0;
        tag=TAGNONE;
    }
}f[N];
int x,id[N],tot,n,ru[N],rt,pos,len,d[N],m,cnt;
char s[20];
int get()
{
    if(tot==0) return ++cnt;
    int x=ru[tot--];
    return x;
}
void c_val(int x,int y)
{
    if(!x) return ;
    f[x].tag=f[x].val=y;
    f[x].sum=y*f[x].size;
    f[x].prel=f[x].prer=max(0,f[x].sum);
    f[x].res=max(y,f[x].sum);
}
void c_rev(int x)
{
    swap(f[x].ch[0],f[x].ch[1]);
    swap(f[x].prer,f[x].prel);
    f[x].rev^=1;
}
void push_up(int x)
{
    int lc=f[x].ch[0],rc=f[x].ch[1];
    f[x].size=f[lc].size+f[rc].size+1;
    f[x].sum=f[lc].sum+f[rc].sum+f[x].val;
    f[x].res=max(max(f[lc].res,f[rc].res),f[lc].prer+f[rc].prel+f[x].val);
    f[x].prel=max(f[lc].prel,f[lc].sum+f[rc].prel+f[x].val);
    f[x].prer=max(f[rc].prer,f[rc].sum+f[lc].prer+f[x].val);
}
void push_down(int x)
{
    int lc=f[x].ch[0],rc=f[x].ch[1];
    if(f[x].tag!=TAGNONE)
    {
        c_val(lc,f[x].tag);
        c_val(rc,f[x].tag);
        f[x].tag=TAGNONE;
    }
    if(f[x].rev)
    {
        c_rev(lc),c_rev(rc);
        f[x].rev=0;
    }
}
int kth(int k)
{
    int x=rt;
    while(1)
    {
        push_down(x);
        int lc=f[x].ch[0],rc=f[x].ch[1];
        if(f[lc].size+1==k) return x;
        else if(f[lc].size>=k) x=lc;
        else k-=f[lc].size+1,x=rc;
    }
}
void rotate(int x)
{
    int y=f[x].fa,z=f[y].fa;
    int wh=(x==f[y].ch[1]);
    f[f[x].ch[wh^1]].fa=y;
    f[y].ch[wh]=f[x].ch[wh^1];
    f[x].ch[wh^1]=y;
    f[y].fa=x,f[x].fa=z;
    if(z) f[z].ch[y==f[z].ch[1]]=x;
    push_up(y),push_up(x);
}
void splay(int x,int y)
{
    for(int fx=f[x].fa;fx=f[x].fa,fx!=y;rotate(x))
        if(f[fx].fa!=y) rotate((fx==f[f[fx].fa].ch[1])^(x==f[fx].ch[1])?x:fx);
    if(!y) rt=x;
}
int split(int pos,int len)
{
    int x=kth(pos),y=kth(pos+len+1);
    splay(x,0),splay(y,x);
    return f[y].ch[0];
}
void creat(int x,int y)
{
    f[x].val=f[x].sum=f[x].res=y;
    f[x].prel=f[x].prer=max(y,0);
    f[x].rev=0,f[x].tag=TAGNONE;
    f[x].size=1;
}
void build(int l,int r,int fa)
{
    int mid=(l+r)>>1;
    int x=id[mid],fx=id[fa];
    if(l==r) creat(x,d[mid]);
    if(l<mid) build(l,mid-1,mid);
    if(mid<r) build(mid+1,r,mid);
    f[x].tag=TAGNONE,f[x].val=d[mid],f[x].fa=fx;
    push_up(x);
    f[fx].ch[mid>=fa]=x;
}
void insert(int x,int len)
{
    for(int i=1;i<=len;i++)
        scanf("%d",&d[i]),id[i]=get();
    build(1,len,0);
    int a=kth(x+1),b=kth(x+2);
    splay(a,0),splay(b,a);
    int c=id[(1+len)>>1];
    f[c].fa=b,f[b].ch[0]=c;
    push_up(b),push_up(a);
}
void remove(int x)
{
    if(f[x].ch[0]) remove(f[x].ch[0]);
    if(f[x].ch[1]) remove(f[x].ch[1]);
    ru[++tot]=x,f[x].clear();
}
void eraser(int k,int len)
{
    int x=split(k,len),y=f[x].fa;
    remove(x);
    f[y].ch[0]=0;
    push_up(y),push_up(f[y].fa);
}
void update(int pos,int len,int k)
{
    int x=split(pos,len);
    c_val(x,k);
    push_up(f[x].fa),push_up(rt);
}
void rever(int pos,int len)
{
    int x=split(pos,len);
    if(f[x].tag!=TAGNONE) return;
    c_rev(x);
    push_up(f[x].fa),push_up(rt);
}
void query(int pos,int len)
{
    int x=split(pos,len);
    printf("%d\n",f[x].sum);
}
int main()
{
    scanf("%d%d",&n,&m);
    f[0].res=d[1]=d[n+2]=-1<<30;
    for(int i=1;i<=n;i++) scanf("%d",&d[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;
    while(m--)
    {
        scanf("%s",s);
        if(s[0]=='M' && s[1]=='A' && s[2]=='X') printf("%d\n",f[rt].res);
        else scanf("%d%d",&pos,&len);
        if(s[0]=='I') insert(pos,len);
        if(s[0]=='D') eraser(pos,len);
        if(s[0]=='M' && s[1]=='A' && s[2]=='K')
            scanf("%d",&x),update(pos,len,x);
        if(s[0]=='R') rever(pos,len);
        if(s[0]=='G') query(pos,len);
    }
    return 0;
}

 

标签:ch,数列,int,pos,len,splay,fa,NOI2005,lc
来源: https://www.cnblogs.com/hsez-cyx/p/12247579.html