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
HINT
Source
辣鸡题目,卡我常数!
最后交了Claris代码….
但是PA原数据是A了的
TLE code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define MAXN 200010
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,m,Q;
void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
int sta[MAXN],top;
int f[MAXN];
map<int,bool> del[MAXN>>1];
int find(int x) { return f[x]==x?x:f[x]=find(f[x]); }
struct edge
{
int u,v,id;
bool operator <(const edge& a)const { return u==a.u?v<a.v:u<a.u; }
}e[MAXN];
struct Query { int opt,u,v,ans; }q[MAXN];
struct Splay
{
int ch[2],fa,sum,val;
bool rev,flag;
}tree[MAXN];
inline bool is_root(int x) { return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x; }
inline void push_up(int x) { tree[x].sum=tree[x].val|tree[tree[x].ch[0]].sum|tree[tree[x].ch[1]].sum; }
inline void push_down(int x)
{
if (!x) return;
int l=tree[x].ch[0],r=tree[x].ch[1];
if (tree[x].flag)
{
tree[l].sum=tree[l].val=0;tree[r].sum=tree[r].val=0;
tree[l].flag=1;tree[r].flag=1;tree[x].flag=0;
}
if (tree[x].rev)
{
tree[l].rev^=1;tree[r].rev^=1;
swap(tree[x].ch[0],tree[x].ch[1]);tree[x].rev^=1;
}
}
inline void rot(int x)
{
int y=tree[x].fa,z=tree[y].fa,l=tree[y].ch[1]==x,r=l^1;
if (!is_root(y)) tree[z].ch[tree[z].ch[1]==y]=x;
tree[x].fa=z;tree[y].fa=x;tree[tree[x].ch[r]].fa=y;
tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
push_up(y);push_up(x);
}
inline void Splay(int x)
{
top=0;sta[++top]=x;
for (int i=x;!is_root(i);i=tree[i].fa) sta[++top]=tree[i].fa;
while (top) push_down(sta[top--]);
while (!is_root(x))
{
int y=tree[x].fa,z=tree[y].fa;
if (!is_root(y))
{
if ((tree[y].ch[0]==x)^(tree[z].ch[0]==x)) rot(x);
else rot(y);
}
rot(x);
}
}
inline void access(int x) { for (int i=0;x;i=x,x=tree[x].fa) Splay(x),tree[x].ch[1]=i,push_up(x); }
inline void make_root(int x) { access(x);Splay(x);tree[x].rev^=1; }
inline void link(int x,int y) { make_root(x);tree[x].fa=y; }
inline void ins(int x,int y)
{
int p=find(x),q=find(y);
if (p!=q)
{
f[p]=q;n++;tree[n].sum=tree[n].val=1;
link(x,n);link(y,n);
return;
}
make_root(x);access(y);Splay(y);tree[y].sum=tree[y].val=0;tree[y].flag=1;
}
inline int query(int x,int y)
{
int p=find(x),q=find(y);
if (p!=q) return 1;
make_root(x);access(y);Splay(y);return tree[y].sum;
}
int main()
{
in(n);in(m);in(Q);int u,v,t;char ch[3];
for (int i=1;i<=n;i++) f[i]=i;
for (int i=1;i<=m;i++)
{
in(u);in(v);if (u>v) swap(u,v);
e[i].u=u;e[i].v=v;e[i].id=i;
}
for (int i=1;i<=Q;i++)
{
scanf("%s",ch);in(u);in(v);if (u>v) swap(u,v);
q[i].opt=ch[0]=='P';q[i].u=u;q[i].v=v;
if (ch[0]=='Z') del[q[i].u][q[i].v]=1;
}
for (int i=1;i<=m;i++)
{
if (del[e[i].u][e[i].v]) continue;
int p=find(e[i].u),q=find(e[i].v);
if (p==q) continue;
f[p]=q;n++;tree[n].sum=tree[n].val=1;
link(e[i].u,n);link(e[i].v,n);del[e[i].u][e[i].v]=1;
}
for (int i=1;i<=m;i++) if (!del[e[i].u][e[i].v]) ins(e[i].u,e[i].v);
for (int i=Q;i;i--)
if (q[i].opt==0) ins(q[i].u,q[i].v);
else q[i].ans=query(q[i].u,q[i].v);
for (int i=1;i<=Q;i++) if (q[i].opt) puts(q[i].ans?"NIE":"TAK");
}
AC code自己去Claris Blog看..