• P2042 [NOI2005]维护数列 平衡树


    最大序列和小白逛公园做过 

    区间修改的优先级高于区间翻转的优先级(之前有题01串翻转)

    序列维护平衡树 平衡树维护的是下标  因此中序遍历就是原序列

    每个结点维护的都是结点  不像线段树可以维护区间  所以build 的操作有一些不一样 

    这题还卡空间  所以要弄一个简单的回收操作

    注意up的顺序  必须从下到上  因为这个wa了好久

    非常好(难调)的平衡树题

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    typedef pair<int,int>pii;
    //////////////////////////////////
    const int N=2e6+10;
    queue<int>q;
    
    int lmax[N],rmax[N],siz[N],son[N][2],id[N],sum[N],maxans[N],fa[N],lson,rson,col[N],rev[N],root,v[N],ncnt,a[N],m,n;
    
    int chk(int x)
    {
        return son[fa[x]][1]==x;
    }
    
    void up(int pos)
    {
        lson=son[pos][0],rson=son[pos][1];
        sum[pos]=sum[lson]+sum[rson]+v[pos];
        siz[pos]=siz[lson]+siz[rson]+1;
        lmax[pos]=max(lmax[lson],sum[lson]+v[pos]+lmax[rson]);
        rmax[pos]=max(rmax[rson],sum[rson]+v[pos]+rmax[lson]);
        maxans[pos]=max(max(maxans[lson],maxans[rson]),v[pos]+rmax[lson]+lmax[rson]);
    }
    void down(int pos)
    {
        lson=son[pos][0];rson=son[pos][1];
        if(col[pos])
        {
            col[pos]=rev[pos]=0;//要删除区间翻转操作
            if(lson)col[lson]=1,v[lson]=v[pos],sum[lson]=v[pos]*siz[lson];
            if(rson)col[rson]=1,v[rson]=v[pos],sum[rson]=v[pos]*siz[rson];
            if(v[pos]>=0)
            {
                if(lson)maxans[lson]=rmax[lson]=lmax[lson]=sum[lson];
                if(rson)maxans[rson]=rmax[rson]=lmax[rson]=sum[rson];
            }
            else
            {
                if(lson)lmax[lson]=rmax[lson]=0,maxans[lson]=v[pos];
                if(rson)lmax[rson]=rmax[rson]=0,maxans[rson]=v[pos];
            }
        }
        if(rev[pos])
        {
            rev[pos]=0;
            rev[lson]^=1;rev[rson]^=1;
            swap(lmax[lson],rmax[lson]);
            swap(lmax[rson],rmax[rson]);
            swap(son[lson][0],son[lson][1]);
            swap(son[rson][0],son[rson][1]);
        }
    }
    
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],k=chk(x),w=son[x][k^1];
        son[y][k]=w;fa[w]=y;
        son[z][chk(y)]=x;fa[x]=z;
        son[x][k^1]=y;fa[y]=x;
        up(y);up(x);//up必须自下往上的  我这里写成up(x),up(y)就一直wa
    }
    
    void splay(int x,int goal=0)
    {
        while(fa[x]!=goal)
        {
            int y=fa[x],z=fa[y];
            if(z!=goal)
            {
                if(chk(x)==chk(y))rotate(y);
                else rotate(x);
            }
            rotate(x);
        }
        if(!goal)root=x;
    }
    
    int find1(int x,int k)
    {
        down(x);
        if(siz[son[x][0]]+1==k)return x;
        if(siz[son[x][0]]>=k)return find1(son[x][0],k);
        else return find1(son[x][1],k-siz[son[x][0]]-1);
    }
    
    void recycle(int x)
    {
        if(son[x][0])recycle(son[x][0]);
        if(son[x][1])recycle(son[x][1]);
        q.push(x);
        son[x][0]=son[x][1]=col[x]=rev[x]=fa[x]=0;
    }
    
    int split(int k,int tot)
    {
        int x=find1(root,k),y=find1(root,k+tot+1);
        splay(x);splay(y,x);
        return son[son[root][1]][0];
    }
    
    int qsum(int k,int tot)
    {
        return sum[split(k,tot)];
    }
    
    void upsum(int k,int tot,int val)
    {
        int x=split(k,tot);
        int y=fa[x];
        col[x]=1;
        v[x]=val;sum[x]=siz[x]*val;
        if(v[x]>=0)maxans[x]=lmax[x]=rmax[x]=sum[x];
        else lmax[x]=rmax[x]=0,maxans[x]=val;
        up(y);up(fa[y]);
    }
    
    void rever(int k,int tot)
    {
        int x=split(k,tot),y=fa[x];
        if(!col[x])
        {
            rev[x]^=1;
            swap(son[x][0],son[x][1]);
            swap(lmax[x],rmax[x]);
            up(y);up(fa[y]);
        }
    }
    
    void del(int k,int tot)
    {
        int x=split(k,tot),y=fa[x];
        recycle(x);
        son[y][0]=0;
        up(y);up(fa[y]);
    }
    
    void build(int l,int r,int f)
    {
        int mid=(l+r)>>1,now=id[mid],pre=id[f];
        if(l==r)
        {
            maxans[now]=sum[now]=a[l];
            col[now]=rev[now]=0;
            lmax[now]=rmax[now]=max(0,a[l]);
            siz[now]=1;
        }
        if(l<mid)build(l,mid-1,mid);
        if(r>mid)build(mid+1,r,mid);
        v[now]=a[mid];fa[now]=pre;
        up(now);son[pre][mid>=f]=now;
    }
    
    void insert(int k,int tot)
    {
        rep(i,1,tot)scanf("%d",&a[i]);
        rep(i,1,tot)
        {
            if(!q.empty())id[i]=q.front(),q.pop();
            else id[i]=++ncnt;
        }
        build(1,tot,0);
        int z=id[(1+tot)>>1];
        int x=find1(root,k+1),y=find1(root,k+2);
        splay(x);splay(y,x);
    
        fa[z]=y;son[y][0]=z;
        up(y);up(x);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        a[1]=a[n+2]=maxans[0]=-inf;
        rep(i,1,n)scanf("%d",&a[i+1]);
        rep(i,1,n+2)id[i]=i;
        build(1,n+2,0);
        root=(3+n)>>1;ncnt=n+2;
        int k,tot,val;
        char ch[10];
        int jjj=0;
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0]!='M'||ch[2]!='X')scanf("%d%d",&k,&tot);
            if(ch[0]=='I')insert(k,tot);
            if(ch[0]=='D')del(k,tot);
            if(ch[0]=='M')
            {
                if(ch[2]=='X')printf("%d
    ",maxans[root]);
                else scanf("%d",&val),upsum(k,tot,val);
            }
            if(ch[0]=='R')rever(k,tot);
            if(ch[0]=='G')printf("%d
    ",qsum(k,tot));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    0615-temp-python web
    ResultSet 转ArrayList
    svn与git
    日期与时间
    springboot 注解
    函数式编程
    几个O
    springboot框架中的异步执行
    JDBC
    mysql 导出表结构
  • 原文地址:https://www.cnblogs.com/bxd123/p/11301602.html
Copyright © 2020-2023  润新知