其他分享
首页 > 其他分享> > bzoj 4573 大森林

bzoj 4573 大森林

作者:互联网

bzoj 4573 大森林

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
    int x=0;
    bool pos=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            pos=0;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return pos?x:-x;
}
const int MAXN=3e5+10;
struct query{
    int pos,op,x,y;
    bool operator < (const query &rhs) const
        {
            return pos==rhs.pos?op<rhs.op:pos<rhs.pos;
        }
}q[MAXN];
namespace LCT{
    int stk[MAXN],tp;
    int tot;
    struct node{
        int ch[2],fa;
        int rev;
        int siz,val;
        node()
            {
                fa=ch[0]=ch[1]=0;
                rev=0;
                siz=val=0;
            }
    }tree[MAXN];
    #define root tree[x]
    #define lson tree[root.ch[0]]
    #define rson tree[root.ch[1]]
    inline void pushup(int x)
        {
            root.siz=lson.siz+root.val+rson.siz;
        }
    void inverse(int x)
        {
            swap(root.ch[0],root.ch[1]);
            root.rev^=1;
        }
    void pushdown(int x)
        {
            if(root.rev)
                {
                    if(root.ch[0])
                        inverse(root.ch[0]);
                    if(root.ch[1])
                        inverse(root.ch[1]);
                    root.rev=0;
                }
        }
    bool isroot(int x)
        {
            int y=root.fa;
            return tree[y].ch[0]!=x && tree[y].ch[1]!=x;
        }
    void rotate(int x)
        {
            int y=tree[x].fa,z=tree[y].fa;
            int k=tree[y].ch[1]==x;
            if(!isroot(y))
                tree[z].ch[tree[z].ch[1]==y]=x;
            tree[x].fa=z;
            tree[tree[x].ch[k^1]].fa=y;
            tree[y].ch[k]=tree[x].ch[k^1];
            tree[x].ch[k^1]=y;
            tree[y].fa=x;
            pushup(y);
            pushup(x);
        }
    void splay(int x)
        {
            tp=0;
            stk[++tp]=x;
            for(int pos=x;!isroot(pos);pos=tree[pos].fa)
                stk[++tp]=tree[pos].fa;
            while(tp)
                pushdown(stk[tp--]);
            while(!isroot(x))
                {
                    int y=tree[x].fa,z=tree[y].fa;
                    if(!isroot(y))
                        (tree[y].ch[0]==x)^(tree[z].ch[0]==y)?rotate(x):rotate(y);
                    rotate(x);
                }
            pushup(x);
        }
    int Access(int x)
        {
            int y;
            for(y=0;x;y=x,x=tree[x].fa)
                {
                    splay(x);
                    tree[x].ch[1]=y;
                    pushup(x);
                }
            return y;
        }
    void makeroot(int x)
        {
            Access(x);
            splay(x);
            inverse(x);
        }
    int findroot(int x)
        {
            Access(x);
            splay(x);
            while(tree[x].ch[0])
                x=tree[x].ch[0];
            return x;
        }
    void split(int x,int y)
        {
            makeroot(x);
            Access(y);
            splay(y);
        }
    void Link(int x,int y)
        {
            makeroot(x);
            tree[x].fa=y;
        }
    void Cut(int x)
        {
            Access(x);
            splay(x);
            tree[tree[x].ch[0]].fa=0;
            tree[x].ch[0]=0;
            pushup(x);
        }
}
using namespace LCT;
int solve(int x,int y)
{
    int ans=0;
    Access(x);
    splay(x);
    ans+=tree[x].siz;
    int lca=Access(y);
    splay(y);
    ans+=tree[y].siz;
    Access(lca);
    splay(lca);
    ans-=2*tree[lca].siz;
    return ans;
}
void newnode(int v)
{
    int x=++tot;
    root.val=root.siz=v;
}
int n,m;
int last,id[MAXN],idd,cnt,L[MAXN],R[MAXN],qs;
inline void insq(int pos,int op,int x,int y)
{
    ++cnt;
    q[cnt].pos=pos,q[cnt].op=op;
    q[cnt].x=x,q[cnt].y=y;
}
int ans[MAXN];
int main()
{
    tot=0;
    n=read(),m=read();
    newnode(1),idd=1,L[1]=1,R[1]=n,id[1]=1;
    newnode(0),last=2,Link(2,1);
    for(int i=1;i<=m;++i)
        {
            int type=read();
            if(type==0)
                {
                    int l=read(),r=read();
                    newnode(1);
                    L[++idd]=l,R[idd]=r,id[idd]=tot;
                    insq(1,i-m,tot,last);
                }
            else if(type==1)
                {
                    int l=read(),r=read(),x=read();
                    l=max(l,L[x]),r=min(r,R[x]);
                    if(l<=r)
                        {
                            newnode(0);
                            Link(tot,last);
                            insq(l,i-m,tot,id[x]);
                            insq(r+1,i-m,tot,last);
                            last=tot;
                        }
                }
            else
                {
                    int x=read(),u=read(),v=read();
                    insq(x,++qs,id[u],id[v]);
                }
        }
    sort(q+1,q+cnt+1);
    for(int i=1,j=1;i<=n;++i)
        {
            for(;j<=cnt && q[i].pos==i;++j)
                {
                    if(q[j].op<=0)
                        {
                            Cut(q[j].x);
                            Link(q[j].x,q[j].y);
                        }
                    else
                        ans[q[j].op]=solve(q[j].x,q[j].y);
                }
        }
    for(int i=1;i<=qs;++i)
        printf("%d\n",ans[i]);
    return 0;
}

标签:ch,const,int,pos,getchar,4573,虚点,bzoj,森林
来源: https://www.cnblogs.com/jklover/p/10414862.html