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
原文地址:https://www.cnblogs.com/bxd123/p/11301602.html