zoukankan      html  css  js  c++  java
  • [BZOJ 3223] 文艺平衡树

    Link:

    BZOJ 3223 传送门

    Solution:

    $Splay$对序列操作的模板题

    核心思想就是将$L-1$移到根,$R+1$移至$L-1$的下方,从而约束出区间$[L,R]$进行操作

    对于此题仅要求将区间翻转,因此只要将左右子树交换即可

    但同时类似于线段树要打上懒惰标记来保证复杂度,每次查询第$K$大时下放标记

    Tips:

    1、对于此题不再关心每个数的权值,而只关心其在序列中的编号

    而这个节点的排名($sz[ch[x][0]]+1$)就是其当前的序号

    2、为了处理$[1,n]$等边界情况,新增$1,n+2$作为真·边界

    3、一开始可以通过分治直接建树,不用一个个$insert$,但要将$f[rt]$置为$0$!!!

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN=1e5+10;
    int n,m,rt,l,r,sz[MAXN],f[MAXN],ch[MAXN][2],tag[MAXN];
    
    void pushup(int x)
    {sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
    
    void pushdown(int x)
    {
        if(!tag[x]) return;
        tag[ch[x][1]]^=1;tag[ch[x][0]]^=1;
        swap(ch[x][0],ch[x][1]);tag[x]=0;
    }
    
    void Build(int l,int r,int anc)
    {
        if(l>r) return;
        int mid=(l+r)/2;
        if(mid<anc) ch[anc][0]=mid;
        else ch[anc][1]=mid;
        sz[mid]=1;f[mid]=anc;
        if(l==r) return;
        
        Build(l,mid-1,mid);Build(mid+1,r,mid);
        pushup(mid);
    }
    
    void Print(int x)
    {
        pushdown(x);
        if(ch[x][0]) Print(ch[x][0]);
        if(x>1&&x<n+2) printf("%d ",x-1);
        if(ch[x][1]) Print(ch[x][1]);
    }
    
    void Rotate(int x)
    {
        int y=f[x],z=f[y],k=(ch[y][1]==x);
        ch[z][ch[z][1]==y]=x;f[x]=z;
        ch[y][k]=ch[x][k^1];f[ch[x][k^1]]=y;
        ch[x][k^1]=y;f[y]=x;
        pushup(x);pushup(y);
    }
    
    void Splay(int x,int up)
    {
        while(f[x]!=up)
        {
            int y=f[x],z=f[y];
            if(z!=up) (ch[y][1]==x)^(ch[z][1]==y)?Rotate(x):Rotate(y);
            Rotate(x);
        }
        if(!up) rt=x;
    }
    
    int Kth(int x)
    {
        int k=rt;
        while(true)
        {
            pushdown(k);
            if(x==sz[ch[k][0]]+1) return k;
            else if(sz[ch[k][0]]>=x) k=ch[k][0];
            else x-=sz[ch[k][0]]+1,k=ch[k][1];
        }
    }
    
    void Reverse(int l,int r)
    {
        int x=Kth(l),y=Kth(r+2);
        Splay(x,0);Splay(y,x);
        tag[ch[ch[rt][1]][0]]^=1;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        rt=(n+3)/2;Build(1,n+2,rt);f[rt]=0;
        
        for(int i=1;i<=m;i++)
            scanf("%d%d",&l,&r),Reverse(l,r);
        Print(rt);
        return 0;
    }
  • 相关阅读:
    zoj 1239 Hanoi Tower Troubles Again!
    zoj 1221 Risk
    uva 10192 Vacation
    uva 10066 The Twin Towers
    uva 531 Compromise
    uva 103 Stacking Boxes
    稳定婚姻模型
    Ants UVA
    Golden Tiger Claw UVA
    关于upper、lower bound 的探讨
  • 原文地址:https://www.cnblogs.com/newera/p/9338199.html
Copyright © 2011-2022 走看看