CODE[VS] 4655 序列终结者 —— splay区间更新,区间翻转,区间求最大值模板

题意:

This way

题解:

wa了好久,它这个pushdown的时候mx值也要加的啊,我以为它还会up更新呢。
挺简单的吧,这个区间更新和区间翻转的原理一样,都是将左端点的左边与右端点的右边翻上去,然后对keytree打上标记,这样down的时候就会更新了

#include
using namespace std;
#define keytree ch[ch[root][1]][0]
#define L(x) ch[x][0]
#define R(x) ch[x][1]
#define N 300005
int ch[N][2],pre[N],cnt[N],size[N],val[N],rev[N],key[N];
int tot,root;
int n,m,mx[N],f[N];
void newnode(int &u,int fa,int KEY)
{
    u=++tot;
    ch[u][0]=ch[u][1]=rev[u]=0;
    pre[u]=fa;size[u]=1;
    val[u]=mx[u]=0;
    key[u]=KEY;
}
void up(int u)
{
    size[u]=1+size[L(u)]+size[R(u)];
    mx[u]=val[u];
    if(L(u))mx[u]=max(mx[u],mx[L(u)]);
    if(R(u))mx[u]=max(mx[u],mx[R(u)]);
}
void down(int u)
{
    if(rev[u])
    {
        if(L(u))rev[L(u)]^=1;
        if(R(u))rev[R(u)]^=1;
        swap(L(u),R(u));
        rev[u]=0;
    }
    if(f[u])
    {
        if(L(u))f[L(u)]+=f[u],val[L(u)]+=f[u],mx[L(u)]+=f[u];
        if(R(u))f[R(u)]+=f[u],val[R(u)]+=f[u],mx[R(u)]+=f[u];
        //val[u]+=f[u];
        f[u]=0;
    }
}
void rotate(int u,int kind)//kind表示u在fa的哪一边
{
    int fa=pre[u];
    down(fa);down(u);
    ch[fa][kind]=ch[u][!kind];
    pre[ch[u][!kind]]=fa;
    if(pre[fa])ch[pre[fa]][ch[pre[fa]][1]==fa]=u;
    pre[u]=pre[fa];
    ch[u][!kind]=fa;
    pre[fa]=u;
    up(fa);up(u);
}
void splay(int u,int goal)
{
    int fa,kind;
    down(u);
    while(pre[u]!=goal)
    {
        if(pre[pre[u]]==goal)
        {
            down(pre[u]);down(u);
            rotate(u,R(pre[u])==u);
        }
        else
        {
            fa=pre[u];
            down(pre[u]);down(fa);down(u);
            kind=R(pre[fa])==fa;
            if(ch[fa][kind]!=u)//不在同一侧
            {
                rotate(u,!kind);
                rotate(u,kind);
            }
            else
            {
                rotate(fa,kind);
                rotate(u,kind);
            }
        }
    }
    up(u);
    if(goal==0)root=u;
}
int getkth(int u,int k)//第k个键值的点的编号
{
    down(u);
    int s=size[L(u)]+1;
    if(s==k) return u;
    if(s>k) return getkth(L(u),k);
    else return getkth(R(u),k-s);
}
void build(int &u,int l,int r,int fa)//按pos为键值
{                        //val为数的大小 a存数的大小
    if(l>r)return ;
    int mid=(l+r)>>1;
    newnode(u,fa,mid);
    build(L(u),l,mid-1,u);
    build(R(u),mid+1,r,u);
    up(u);
}
void init()
{
    root=tot=0;
    L(root)=R(root)=pre[root]=size[root]=rev[root]=0;
    newnode(root,0,0);
    newnode(R(root),root,N);
    build(keytree,1,n,R(root));
    up(R(root));
    up(root);
}
//--------------------------------------------------基本操作
int main()
{
    scanf("%d%d",&n,&m);
    init();
    while(m--)
    {
        int op,l,r,x;
        scanf("%d%d%d",&op,&l,&r);
        int pos=getkth(root,l);
        splay(pos,0);
        pos=getkth(root,r+2);
        splay(pos,root);
        if(op==1)
        {
            scanf("%d",&x);
            val[keytree]+=x;
            f[keytree]+=x;
            mx[keytree]+=x;
            up(root);
        }
        else if(op==2)
            rev[keytree]^=1;
        else
            printf("%d\n",mx[keytree]);
    }
    return 0;
}
/*
4 4
1 1 3 -2
1 2 4 -1
2 1 3
3 2 3
*/



你可能感兴趣的:(splay)