luogu 2542 [AHOI2005] route planning

Topic links: luogu2542

First consider how to modify the operation should be completed no inquiries: Use \ (Tarjan \) to be reduced by double point, the answer is the distance between the two points after shrinking finish

Then consider modifying the situation, noting that only modify delete an operation can then consider adding reverse side

Use \ (LCT \) maintenance plus side this process, consider the impact of each plus a side view of the mid-point of the two-: If even became a ring, then the ring will be shrunk to a point

Using segment tree marking thoughts, we'll open a disjoint-set to maintain the number of each point after point reduction. Specifically, for every plus side, we first find the two sides even after the reduction in the number of completion point, if not in words a communication block is directly connected to the edge, or we need to consider the points marked reduction in the disjoint-set tag . Note that we \ (makeroot (x), access (y) \) after the splay tree maintenance is \ (x-> y \) in the chain, so direct violence will \ (x \) right son emptied, and disjoint-set on their father set to \ (x \)

But this is only a marking process, and we do not have information subtree substantial changes

As the need to query sub-tree information \ (Access \) , then be in the above hands, the original \ (x = fa [x] \) becomes \ (fa [x] \) that shrunk to the point that is can

More specific details look at the code

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
struct node{
    int u,v;
}edge[200200];
struct qnode{
    int op,x,y;
}q[200200];
int n,m,siz[30050],fa[30030],ch[30030][2],pa[30030],tag[30030],sta[30030],tot=0,tot1=0,ans[40030];
map<pair<int,int>,int> used;
int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

bool isroot(int x) {return ((ch[fa[x]][0]!=x) && (ch[fa[x]][1]!=x));}
void pushup(int x) {siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;}
void puttag(int x) {swap(ch[x][0],ch[x][1]);tag[x]^=1;}
int find(int x) {if (pa[x]==x) return x;pa[x]=find(pa[x]);return pa[x];}
void pushdown(int x)
{
    if (tag[x])
    {
        if (ch[x][0]) puttag(ch[x][0]);
        if (ch[x][1]) puttag(ch[x][1]);
        tag[x]=0;
    }
}

void rotate(int x)
{
    int y=fa[x],z=fa[y],k=(ch[y][1]==x),w=ch[x][k^1];
    if (!isroot(y)) ch[z][ch[z][1]==y]=x;
    ch[x][k^1]=y;ch[y][k]=w;
    if (w) fa[w]=y;fa[y]=x;fa[x]=z;
    pushup(y);pushup(x);
}

void splay(int x)
{
    int now=x,tp=0;sta[++tp]=now;
    while (!isroot(now)) {now=fa[now];sta[++tp]=now;}
    while (tp) {pushdown(sta[tp]);tp--;}
    while (!isroot(x))
    {
        int y=fa[x],z=fa[y];
        if (!isroot(y))
        {
            if ((ch[y][0]==x)^(ch[z][0]==y)) rotate(x);else rotate(y);
        }
        rotate(x);
    }
    pushup(x);
}

void access(int x)
{
    int y=0;
    while (x)
    {
        splay(x);ch[x][1]=y;pushup(x);
        y=x;fa[y]=find(fa[y]);x=find(fa[x]);
    }
}

int findroot(int x)
{
    access(x);splay(x);
    while (ch[x][0])
    {
        pushdown(x);x=ch[x][0];
    }
    splay(x);return x;
}

void makeroot(int x) {access(x);splay(x);puttag(x);}
void split(int x,int y) {makeroot(x);access(y);splay(y);}
void del(int x,int fx) {if (x) {pa[x]=fx;del(ch[x][0],fx);del(ch[x][1],fx);}}
void link(int x,int y)
{
    if (x==y) return;
    makeroot(x);
    if (findroot(y)!=x)
    {
        fa[x]=y;pushup(y);
    }
    else
    {   
        del(ch[x][1],x);
        ch[x][1]=0;pushup(x);
    }
}

int main()
{
    n=read();m=read();
    rep(i,1,m)
    {
        edge[i].u=read();edge[i].v=read();
    }
    while (1)
    {
        int op=read();if (op==-1) break;
        q[++tot].op=op;
        q[tot].x=read();q[tot].y=read();
        if (!op) used[mp(q[tot].x,q[tot].y)]=used[mp(q[tot].x,q[tot].y)]=1;
    }
    rep(i,1,n) {siz[i]=1;pa[i]=i;}
    rep(i,1,m)
    {
        if (used.count(mp(edge[i].u,edge[i].v))==0) 
        {
            int fx=find(edge[i].u),fy=find(edge[i].v);
            link(fx,fy);
        }
    }
    per(i,tot,1)
    {
        int fx=find(q[i].x),fy=find(q[i].y);
        if (q[i].op)
        {
            split(fx,fy);ans[++tot1]=siz[fy]-1;
        }
        else link(fx,fy);
        //rep(j,1,n) cout << find(j) << " ";cout << endl;
    }
    per(i,tot1,1) printf("%d\n",ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/encodetalker/p/11071755.html