luogu 2542 [AHOI2005]ルート計画

トピックリンク:luogu2542

最初の操作は一切の問い合わせを完了すべきではない修正する方法を検討してください:使用\(Tarjan \)は二重のポイントによって減少することが、答えは仕上げを縮小した後、2点間の距離であります

その後だけにして裏面を追加することを検討することができ、操作を削除、変更することを留意し、状況を修正することを検討

使用\(LCT \)メンテナンスプラス側、このプロセスは、それぞれの影響に加えて、二の中間点の側面図を考えてみます。でもリングになった場合には、リングがポイントに縮小されます

考えをマーキングセグメントツリーを使用して、我々はポイント還元後の各点の数を維持するためにばらばらのセット開きます。具体的には、すべてのプラス側のために、言葉で通信ブロックを直接エッジに接続されていない場合には、まず、偶数終了点の数が減少した後に両面を見つける、または我々はポイントを互いに素なセットタグの著しい減少を考慮する必要が。私たちがいることに注意してください(makeroot(x)は、アクセス\ \)(y)をスプレー木のメンテナンス後にはされて(x軸>のy \)を\チェーンで、その直接の暴力はします\(X \)右の息子は、空にそして、するように設定父親に互いに素セット(X \)\

しかし、これは唯一のマーキングプロセスであり、我々は情報サブツリー大幅な変更はありません

サブツリー情報クエリに必要として\(アクセス\)を上記の手であっても、その後、元の\(X = FAが[X] \) となる(FA [X]を\)\である点に縮小こと缶

より具体的な詳細は、コードを見て

#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;
}

おすすめ

転載: www.cnblogs.com/encodetalker/p/11071755.html