hdu5458 LCA+并查集+dfs序+树状数组

神题,看着别人代码学习

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iomanip>
#include<vector>
#include<set>
#include<map>
#include<queue>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

#define rep(i,k,n) for(int i=(k);i<=(n);i++)
#define rep0(i,n) for(int i=0;i<(n);i++)
#define red(i,k,n) for(int i=(k);i>=(n);i--)
#define sqr(x) ((x)*(x))
#define clr(x,y) memset((x),(y),sizeof(x))
#define pb push_back
#define mod 1000000007
const int maxn=30010;
const int maxq=100010;
const int N=15;

int n,m,q;
int fa[maxn][N];
int beg[maxn],ed[maxn],dtime,dep[maxn],ans[maxq];

struct edge
{
    int to,del;
    edge(int x):to(x),del(0){}
    bool operator < (const edge &x) const
    {
        if(to!=x.to)return to<x.to;
        return del>x.del;
    }
};

vector<edge> e[maxn];

struct QUERY
{
    int op,u,v;
    void read()
    {
        scanf("%d%d%d",&op,&u,&v);
        if(op==1)
        {
            lower_bound(e[u].begin(),e[u].end(),edge(v))->del=1;
            lower_bound(e[v].begin(),e[v].end(),edge(u))->del=1;
        }
    }
}Q[maxq];

struct BIT
{
    int v[maxn];
    void init()
    {
        clr(v,0);
    }
    void add(int x,int k)
    {
        for(;x<=n;x+=x&-x)v[x]+=k;
    }
    void update(int L,int R,int k)
    {
        add(L,k);
        add(R+1,-k);
    }
    int qry(int x)
    {
        int ret=0;
        for(;x;x-=x&-x)ret+=v[x];
        return ret;
    }
}B;

void dfs(int u,int F,int deep)
{
    if(F)e[u].erase(lower_bound(e[u].begin(),e[u].end(),edge(F)));
    beg[u]=++dtime;
    dep[u]=deep;
    fa[u][0]=F;

    for(int i=0;i<e[u].size();i++)
    {
        if(e[u][i].del || beg[e[u][i].to])continue;
        e[u][i].del=1;
        dfs(e[u][i].to,u,deep+1);
    }

    ed[u]=dtime;
    B.update(beg[u],ed[u],1);
}

void Lca_init()
{
    for(int i=1;i<N;i++)rep(j,1,n)fa[j][i]=fa[fa[j][i-1]][i-1];
}

int lca(int u,int v)
{
    if(dep[u]<dep[v])swap(u,v);
    int t=dep[u]-dep[v];
    for(int i=0;i<N;i++)if((1<<i)&t)u=fa[u][i];
    if(u==v)return u;
    for(int i=N-1;i>=0;i--)
    {
        if(fa[u][i]!=fa[v][i])
        {
            u=fa[u][i];
            v=fa[v][i];
        }
    }
    return fa[u][0];
}

struct UNION
{
    int f[maxn];
    void init()
    {
        rep(i,1,n)f[i]=i;
        rep(i,1,n)for(int j=0;j<e[i].size();j++)
        {
            if(e[i][j].del)continue;
            merge(i,e[i][j].to);
        }
    }
    int getf(int x)
    {
        return x==f[x]?x:f[x]=getf(f[x]);
    }
    void mergef(int u,int ff)
    {
        while(u!=ff)
        {
            int t=getf(fa[u][0]);
            f[u]=t;
            B.update(beg[u],ed[u],-1);
            u=t;
        }
    }
    void merge(int u,int v)
    {
        u=getf(u);
        v=getf(v);
        int ff=getf(lca(u,v));
        mergef(u,ff);
        mergef(v,ff);
    }
}U;

void solve()
{
    clr(beg,0);clr(ed,0);
    B.init();
    dtime=0;
    dfs(1,0,1);
    Lca_init();
    U.init();

    int tot=0;
    red(i,q,1)
    {
        int u=U.getf(Q[i].u),v=U.getf(Q[i].v);
        if(Q[i].op==1)
        {
            U.merge(u,v);
        }
        else
        {
            int ff=U.getf(lca(u,v));
            ans[++tot]=B.qry(beg[u])+B.qry(beg[v])-2*B.qry(beg[ff]);
        }
    }
    red(i,tot,1)printf("%d\n",ans[i]);
}

int main()
{
	int T;
	scanf("%d",&T);
	rep(ii,1,T)
	{
	    printf("Case #%d:\n",ii);
	    scanf("%d%d%d",&n,&m,&q);
	    rep(i,1,n)e[i].clear();
	    rep(i,1,m)
	    {
	        int u,v;
	        scanf("%d%d",&u,&v);
	        e[u].pb(edge(v));
	        e[v].pb(edge(u));
	    }
	    rep(i,1,n)sort(e[i].begin(),e[i].end());
	    rep(i,1,q)Q[i].read();
	    solve();
	}

	return 0;
}


你可能感兴趣的:(hdu5458 LCA+并查集+dfs序+树状数组)