• 【BZOJ】1500: [NOI2005]维修数列


    【算法】splay

    【题解】数据结构

    感谢Occult的模板>_<:HYSBZ 1500 维修数列

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int maxn=5e5+10,inf=0x3f3f3f3f;
    int n,m,root,a[maxn],t[maxn][2],f[maxn],A[maxn],L[maxn],R[maxn],M[maxn],sum[maxn],en[maxn],g[maxn],s[maxn];
    //关系类:f父亲 t儿子 | 数值类:num值 L左起最大子段和 R右起最大子段和 M最大子段和 sum和 s结点数 | 标记类:en覆盖标记 g翻转标记
    queue<int>q;
    int read()
    {
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    int Node(int fa,int num)
    {
        int sz=q.front();q.pop();
        t[sz][0]=t[sz][1]=en[sz]=g[sz]=0;
        s[sz]=1;f[sz]=fa;A[sz]=L[sz]=R[sz]=M[sz]=sum[sz]=num;
        return sz;
    }
    void count(int x)//与线段树更新不同,记得加自身 
    {
        L[x]=max(L[t[x][0]],sum[t[x][0]]+A[x]+max(0,L[t[x][1]]));
        R[x]=max(R[t[x][1]],sum[t[x][1]]+A[x]+max(0,R[t[x][0]]));
        M[x]=max(0,R[t[x][0]])+A[x]+max(0,L[t[x][1]]);
        M[x]=max(M[x],max(M[t[x][0]],M[t[x][1]]));
        sum[x]=sum[t[x][0]]+A[x]+sum[t[x][1]];
        s[x]=s[t[x][0]]+1+s[t[x][1]];
    }
    void pushdown(int x)
    {
        if(g[x])
        {
            g[t[x][0]]^=1;g[t[x][1]]^=1;
            swap(L[t[x][0]],R[t[x][0]]);
            swap(L[t[x][1]],R[t[x][1]]);
            swap(t[x][0],t[x][1]);
            g[x]=0;
        }
        if(en[x])
        {
            if(t[x][0])
            {
                en[t[x][0]]=1;
                A[t[x][0]]=A[x];
                sum[t[x][0]]=A[x]*s[t[x][0]];
                L[t[x][0]]=R[t[x][0]]=M[t[x][0]]=A[x]>0?sum[t[x][0]]:A[x];
            }
            if(t[x][1])
            {
                en[t[x][1]]=1;
                A[t[x][1]]=A[x];
                sum[t[x][1]]=A[x]*s[t[x][1]];
                L[t[x][1]]=R[t[x][1]]=M[t[x][1]]=A[x]>0?sum[t[x][1]]:A[x];
            }
            en[x]=0;
        }
    }
    void rotate(int x)
    {
        int k=x==t[f[x]][1];
        int y=f[x];
        t[y][k]=t[x][!k];f[t[x][!k]]=y;
        if(f[y])t[f[y]][y==t[f[y]][1]]=x;f[x]=f[y];f[y]=x;
        t[x][!k]=y;
        L[x]=L[y];R[x]=R[y];M[x]=M[y];sum[x]=sum[y];s[x]=s[y];
        count(y);
    }
    void splay(int x,int r)
    {
        for(int fa=f[r];f[x]!=fa;)//因为y被旋走了,所以要判断f[y] 
        {
            if(f[f[x]]==fa){rotate(x);break;}
            int X=x==t[f[x]][1],Y=f[x]==t[f[f[x]]][1];//等号别打少…… 
            if(X^Y)rotate(x),rotate(x);
             else rotate(f[x]),rotate(x);
        }
    }    
    void find(int &x,int k)
    {
        for(int i=x;i;)
        {
            pushdown(i);
            if(k<=s[t[i][0]]){i=t[i][0];continue;}
            if(k==s[t[i][0]]+1){splay(i,x);x=i;break;}
            k-=s[t[i][0]]+1;i=t[i][1];//else不安全。。。 
        }
    }
    void build(int fa,int &x,int l,int r)
    {
        if(l>r)return;
        int mid=(l+r)>>1;
        x=Node(fa,a[mid]);
        build(x,t[x][0],l,mid-1);
        build(x,t[x][1],mid+1,r);
        count(x);//
    }
    void insert()
    {
        int l=read(),k=read();
        for(int i=1;i<=k;i++)a[i]=read();
        int r;build(0,r,1,k);
        find(root,l+1);find(t[root][1],1);
        t[t[root][1]][0]=r;f[r]=t[root][1];
        count(t[root][1]);count(root);//记得count 
    }
    void erase(int x)
    {
        if(!x)return;
        q.push(x);
        erase(t[x][0]);
        erase(t[x][1]);
    }
    void del()
    {
        int l=read(),k=read();
        find(root,l);find(t[root][1],k+1);
        erase(t[t[root][1]][0]);
        t[t[root][1]][0]=0;
        count(t[root][1]);count(root);//
    }
    void cover()
    {
        int l=read(),k=read(),num=read();
        find(root,l);find(t[root][1],k+1);
        int y=t[t[root][1]][0];
        en[y]=1;A[y]=num;
        sum[y]=s[y]*A[y];
        L[y]=R[y]=M[y]=A[y]>0?sum[y]:A[y];
        count(t[root][1]);count(root);//
    }
    void round()
    {
        int l=read(),k=read();
        find(root,l);find(t[root][1],k+1);
        int y=t[t[root][1]][0];
        g[y]^=1;
        swap(L[y],R[y]);
        count(t[root][1]);count(root);//
    }
    void getsum()
    {
        int l=read(),k=read();
        find(root,l);find(t[root][1],k+1);
        printf("%d
    ",sum[t[t[root][1]][0]]);
    }
    void getM()
    {
        int sz=s[root];
        find(root,1);
        find(t[root][1],sz-1);
        printf("%d
    ",M[t[t[root][1]][0]]);
    }
    char str[20];
    int main()
    {
        n=read();m=read();
        a[0]=a[n+1]=root=0;
        for(int i=1;i<=maxn;i++)q.push(i);
        L[0]=R[0]=M[0]=-inf;//使空结点干扰判断,过程中需保证任何时刻都不应修改到该点的值。 
        for(int i=1;i<=n;i++)a[i]=read();
        build(0,root,0,n+1);
        for(int i=1;i<=m;i++)
        {
            scanf("%s",str);
            if(str[2]=='S')insert();  
            if(str[2]=='L')del();  
            if(str[2]=='K')cover();  
            if(str[2]=='V')round();  
            if(str[2]=='T')getsum();  
            if(str[2]=='X')getM();  
        }
        return 0;
    }
    View Code

    update:现在已改用fhq-treap代替splay。

  • 相关阅读:
    老鸟的Python新手教程
    vs2010经常使用快捷键
    SQL基础--&gt; 约束(CONSTRAINT)
    哈哈,做题了
    【网络协议】TCP中的四大定时器
    JAVA反射机制
    JUnit入门
    怎样将程序猿写出来的程序打包成安装包(最简单的)
    事件传递机制总结
    理解class.forName()
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6916479.html
Copyright © 2020-2023  润新知