zoukankan      html  css  js  c++  java
  • BZOJ3069: [Pa2011]Hard Choice 艰难的选择

    Description

    Byteasar是一个很纠结的人。每次他经过Bytetown的时候都知道有至少2条不同的路径可以选择,这导致他必须花很长时间来决定走哪条路。Byteasar最近听说了Bytetown的修路计划,他可能是唯一一个为此感到高兴的人——他有机会消除他的烦恼。

    在Byteasar一共有n个岔口,连接着m条双向道路。两条路径完全不同当且仅当他们没有公共的道路(但是允许经过相同的岔口)。

    Byteasar想知道:对于两个岔口x y,是否存在一对完全不同的路径。

    Input

    第一行3个整数:n, m, z (2<=n<=100000, 1<=m,z<=100000),分别代表:n个岔口,m条边,事件数z。岔口编号为1~n。

    下面m行:ai, bi (1<=ai,bi<= n, ai!=bi),描述一条边

    然后下面z行描述事件:ti, ci, di (t='Z' or 'P', 1<=ci,di<=n, ci!=di)。事件按照时间排序。

    • t='Z',表示删除一条边(ci, di),保证这条边之前没有被删除。注意,边可以被全部删除!
    • t='P',询问是否存在从ci到di的一对完全不同的路径。

    Output

    对于每组询问,如果存在,输出TAK,否则输出NIE

    Sample Input

    7 8 7
    1 2
    1 3
    1 4
    2 3
    3 4
    3 7
    7 4
    5 6
    Z 1 4
    P 1 3
    P 2 4
    Z 1 3
    P 1 3
    Z 6 5
    P 5 6

    Sample Output

    TAK
    TAK
    NIE
    NIE
     
    做过BZOJ2959长跑的话这道题就很简单了,先时光倒流把删边转化成加边,然后用LCT来维护边-双联通分量并缩环,具体见code。
    我第一次单旋LCT被卡掉!!!外国人太强了!!!看来以后写LCT不能偷懒了。
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #define lc ch[x][0]
    #define rc ch[x][1]
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
    	if(head==tail) {
    		int l=fread(buffer,1,BufferSize,stdin);
    		tail=(head=buffer)+l;
    	}
    	return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    int n,m,z,ans[maxn],pa[maxn],pa2[maxn];
    struct Edge {
    	int u,v;
    	bool operator < (const Edge& ths) const {
    		return u<ths.u||(u==ths.u&&v<ths.v);
    	}
    }E[maxn],Q[maxn];
    int findset(int x) {return x==pa[x]?x:pa[x]=findset(pa[x]);}
    int findrt(int x) {return x==pa2[x]?x:pa2[x]=findrt(pa2[x]);}
    int tp[maxn],del[maxn];
    int pre[maxn],fa[maxn],ch[maxn][2],flip[maxn];
    void pushdown(int x) {
    	if(flip[x]) {
    		flip[lc]^=1;flip[rc]^=1;
    		swap(lc,rc);flip[x]=0;
    	}
    }
    void rotate(int x) {
    	int y=pre[x],z=pre[y],d=ch[y][0]==x;
    	ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y;
    	ch[z][ch[z][1]==y]=x;pre[x]=z;
    	ch[x][d]=y;pre[y]=x;
    }
    int S[maxn],top;
    void splay(int x) {
    	for(int i=x;i;i=pre[i]) S[++top]=i;
    	if(top!=1) fa[x]=fa[S[top]],fa[S[top]]=0;
    	while(top) pushdown(S[top--]);
    	while(pre[x]) {
            int y=pre[x],z=pre[y];
            if(pre[y]) if(ch[y][0]==x^ch[z][0]==y) rotate(x); else rotate(y);
            rotate(x);
        }
    }
    void access(int x) {
    	for(int y=0;x;x=findset(fa[x])) {
    		splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x;
    		ch[x][1]=y;pre[y]=x;y=x;
    	}
    }
    void makeroot(int x) {access(x);splay(x);flip[x]^=1;}
    void link(int x,int y) {makeroot(x);fa[x]=y;}
    void dfs(int x,int y) {
    	if(!x) return;pushdown(x);
    	pa[findset(x)]=findset(y);
    	dfs(ch[x][0],y);dfs(ch[x][1],y);
    	ch[x][0]=ch[x][1]=0;
    }
    void cycle(int x,int y) {
    	makeroot(x);access(y);splay(y);dfs(y,y);
    }
    void Add(int x,int y) {
    	x=findset(x);y=findset(y);if(x==y) return;
    	if(findrt(x)!=findrt(y)) link(x,y),pa2[findrt(x)]=findrt(y);
    	else cycle(x,y);
    }
    int main() {
    	n=read();m=read();z=read();
    	rep(i,1,m) {
    		E[i].u=read(),E[i].v=read();
    		if(E[i].u>E[i].v) swap(E[i].u,E[i].v);
    	}
    	sort(E+1,E+m+1);
    	rep(i,1,z) {
    		char c=Getchar();while(!isalpha(c)) c=Getchar();
    		tp[i]=(c=='P');Q[i].u=read();Q[i].v=read();if(Q[i].u>Q[i].v) swap(Q[i].u,Q[i].v);
    		if(!tp[i]) {
    			int l=1,r=m,mid;
    			while(l<r) if(E[mid=l+r>>1]<Q[i]) l=mid+1; else r=mid;
    			del[l]=1;
    		}
    	}
    	rep(i,1,n) pa[i]=pa2[i]=i;
    	rep(i,1,m) if(!del[i]) Add(E[i].u,E[i].v);
    	dwn(i,z,1) {
    		if(!tp[i]) Add(Q[i].u,Q[i].v);
    		else ans[i]=findset(Q[i].u)==findset(Q[i].v);
    	}
    	rep(i,1,z) if(tp[i]) puts(ans[i]?"TAK":"NIE");
    	return 0;
    }
    

      

  • 相关阅读:
    【转载】USB2.0接口差分信号线设计
    2.4G高频PCB天线设计
    [转]热插拔原理和应用
    [转]or cad drc 错误
    Chrome浏览器任意修改网页内容
    Oracle笔记之约束
    Oracle笔记之表空间
    Oracle笔记之序列(Sequence)
    Oracle笔记之用户管理
    Win7下SQLPlus登录时报错"SP2-1503:无法初始化Oracle调用界面"
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5553791.html
Copyright © 2011-2022 走看看