bzoj1500: [NOI2005]维修数列

Posted invoid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1500: [NOI2005]维修数列相关的知识,希望对你有一定的参考价值。

splay.

就是splay,没别的了。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 600000 + 10;
const int inf = 0x3f3f3f3f;

struct Splay {
    int v[maxn],s[maxn],sum[maxn];
    int l[maxn],r[maxn],f[maxn];
    int maxl[maxn],maxr[maxn],maxs[maxn];
    int same[maxn],rev[maxn];
    int q[maxn+1000],h,t;
    int root;
    
    int newnode() {
        int x=q[h++];
        if(h==maxn) h=0;
        return x;
    }
    
    void recycle(int x) {
        if(x==0) return;
        recycle(l[x]);
        recycle(r[x]);
        q[t++]=x;
        if(t==maxn) t=0;
    }
    
    void reverse(int x) {
        swap(l[x],r[x]);
        swap(maxl[x],maxr[x]);
        rev[x]^=1;    
    }
    
    void make_same(int x,int val) {
        same[x]=v[x]=val;
        sum[x]=s[x]*val; 
        if(val>0) maxl[x]=maxr[x]=maxs[x]=sum[x];
        else {maxl[x]=maxr[x]=0; maxs[x]=val;}
    }
    
    void push(int x) {
        if(same[x]!=inf) {
            make_same(l[x],same[x]);
            make_same(r[x],same[x]);
            same[x]=inf;
            if(rev[x]) rev[x]=0;    
        }
        if(rev[x]) {
            reverse(l[x]);
            reverse(r[x]);
            rev[x]=0;
        }
    }
    
    void update(int x) {    
        sum[x]=sum[l[x]]+sum[r[x]]+v[x];
        maxl[x]=max(maxl[l[x]],sum[l[x]]+v[x]+maxl[r[x]]);
        maxr[x]=max(maxr[r[x]],sum[r[x]]+v[x]+maxr[l[x]]);
        maxs[x]=max(max(maxs[l[x]],maxs[r[x]]),maxr[l[x]]+v[x]+maxl[r[x]]);
        s[x]=s[l[x]]+s[r[x]]+1;
    }
    
    void lr(int x) {
        int y=f[x];
        r[y]=l[x];
        if(l[x]) f[l[x]]=y;
        f[x]=f[y];
        if(root==y) root=x;
        else if(l[f[y]]==y) l[f[y]]=x;
        else r[f[y]]=x;
        f[y]=x; l[x]=y;
        update(y);
        update(x);
    }
    
    void rr(int x) {
        int y=f[x];
        l[y]=r[x];
        if(r[x]) f[r[x]]=y;
        f[x]=f[y];
        if(root==y) root=x;
        else if(l[f[y]]==y) l[f[y]]=x;
        else r[f[y]]=x;
        f[y]=x; r[x]=y;
        update(y);
        update(x);
    }
    
    void rotate(int x) {
        if(l[f[x]]==x) rr(x);
        else lr(x);
    }
    
    void splay(int x,int target=0) {
        while(f[x]!=target) {
            if(f[f[x]]==target) rotate(x);
            else if((l[f[x]]==x)==(l[f[f[x]]]==f[x])) {rotate(f[x]); rotate(x);}
            else {rotate(x); rotate(x);}
        }
    }
    
    int find(int k) {
        int x=root;
        push(x);
        while(k!=s[l[x]]+1) {
            if(k>s[l[x]]+1) {k-=s[l[x]]+1; x=r[x];}
            else x=l[x];
            push(x);
        }    
        return x;
    }
    
    void Insert(int pos,int tot) {
        splay(find(pos+1),0);
        splay(find(pos+2),root);
        build(l[r[root]],r[root],1,tot);
        update(r[root]);
        update(root);    
    }
    
    void Delete(int pos,int tot) {
        splay(find(pos),0);
        splay(find(pos+tot+1),root);
        recycle(l[r[root]]);
        l[r[root]]=0;
        update(r[root]);
        update(root);    
    }
    
    void Make(int pos,int tot,int val) {
        splay(find(pos),0);
        splay(find(pos+tot+1),root);
        make_same(l[r[root]],val);
        update(r[root]);
        update(root);
    }
    
    void Reverse(int pos,int tot) {
        splay(find(pos),0);
        splay(find(pos+tot+1),root);
        reverse(l[r[root]]);
        update(r[root]);
        update(root);
    }
    
    int Get_sum(int pos,int tot) {
        splay(find(pos),0);
        splay(find(pos+tot+1),root);
        return sum[l[r[root]]];
    }
    
    int Max_sum() {
        return maxs[root];
    }
    
    void build(int &x,int fa,int L,int R) {
        if(L>R) {x=0; return;}
        x=newnode(); f[x]=fa; same[x]=inf; rev[x]=0;
        int mid=(L+R)/2;
        build(l[x],x,L,mid-1);
        scanf("%d",&v[x]); 
        build(r[x],x,mid+1,R);
        update(x);
    }
    
    void init(int n) {
        v[0]=v[1]=v[2]=maxs[0]=-inf; 
        same[1]=same[2]=inf;
        r[1]=2; f[2]=1; s[1]=2; s[2]=1;
        root=1;
        update(2); update(1);
        for(int i=3;i<maxn;i++) q[t++]=i;
        
        build(l[r[root]],r[root],1,n);    
        update(r[root]);
        update(root);
    }
    
    /*void debug(int x) {
        if(!x) return;
        //push(x);
        debug(l[x]);
        printf("%d ",v[x]);
        debug(r[x]);
    }*/
}splay;

char op[20];
int n,m,val,tot,pos;

int main() {
    scanf("%d%d",&n,&m);
    splay.init(n);
    
    while(m--) {
        //splay.debug(splay.root);
        scanf("%s",op);
        if(op[0]==I) {
            scanf("%d%d",&pos,&tot);
            splay.Insert(pos,tot);
        }
        else if(op[0]==D) {
            scanf("%d%d",&pos,&tot);
            splay.Delete(pos,tot);    
        }
        else if(op[0]==M && op[2]==K) {
            scanf("%d%d%d",&pos,&tot,&val);
            splay.Make(pos,tot,val);
        }
        else if(op[0]==R) {
            scanf("%d%d",&pos,&tot);
            splay.Reverse(pos,tot);    
        }
        else if(op[0]==G) {
            scanf("%d%d",&pos,&tot);
            printf("%d\n",splay.Get_sum(pos,tot));
        }
        else {
            printf("%d\n",splay.Max_sum());
        }
    }    
    return 0;
}

以上是关于bzoj1500: [NOI2005]维修数列的主要内容,如果未能解决你的问题,请参考以下文章

bzoj:1500: [NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列[splay ***]

BZOJ1500[NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列

bzoj1500 [NOI2005]维修数列

bzoj1500: [NOI2005]维修数列