P4246 [SHOI2008]堵塞的交通
LCT练习题
不妨当做**[模板]动态图连通性(离线可过)**
线段树?那是什么神仙的东西?这种转移还能维护的???
所以考虑LCT
离线可过的想法还是很简单的,每条边在时间轴上都有一个存在时间,然后我们可以考虑线段树分治,然后并查集按秩合并可撤销之类的搞一搞
当然不可能,直接维护删除时间的最大生成树,然后你发现一个询问是否可行是一个树上查询最小值....
如果最小值大于当前询问就不行
调试已删除
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
#define mkp(x,y) (make_pair(x,y))
using namespace std;
const int MAXN = 3e5 + 7;
const int inf = 1e9 + 7;
int n, m, tmp, T, Q;
map<pair<int, int>, int> mp;
int qwq[3][MAXN];
char s[20];
namespace LCT {
#define L ch[x][0]
#define R ch[x][1]
static int ch[MAXN][2], f[MAXN], val[MAXN], minid[MAXN], st[MAXN];
bool r[MAXN];
inline bool nroot(int x) {
return ch[f[x]][0] == x || ch[f[x]][1] == x;
}
inline void pushR(int x) {
L ^= R ^= L ^= R;
r[x] ^= 1;
}
inline void pushdown(int x) {
if(r[x]) {
if(L)pushR(L);
if(R)pushR(R);
r[x] = 0;
}
}
inline void pushup(int x) {
minid[x] = val[minid[L]] < val[minid[R]] ? minid[L] : minid[R];
if(val[x] < val[minid[x]])minid[x] = x;
}
inline void rotate(int x) {
int y = f[x], z = f[y], k = ch[y][1] == x, w = ch[x][!k];
if(nroot(y))ch[z][ch[z][1] == y] = x;
ch[x][!k] = y;
ch[y][k] = w;
if(w)f[w] = y;
f[y] = x;
f[x] = z;
pushup(y);
}
inline void splay(int x) {
int y = x, z = 0;
st[++z] = y;
while(nroot(y))st[++z] = y = f[y];
while(z)pushdown(st[z--]);
while(nroot(x)) {
y = f[x];
z = f[y];
if(nroot(y))rotate((ch[y][0] == x) ^ (ch[z][0] == y) ? x : y);
rotate(x);
}
pushup(x);
}
inline void access(int x) {
for(int y = 0; x; x = f[y = x]) {
splay(x);
R = y;
pushup(x);
}
}
inline void makeroot(int x) {
access(x);
splay(x);
pushR(x);
}
inline void split(int x, int y) {
makeroot(x);
access(y);
splay(y);
}
inline int findroot(int x) {
access(x);
splay(x);
while(L)pushdown(x), x = L;
splay(x);
return x;
}
inline void link(int x, int y) {
split(x, y);
f[x] = y;
}
inline void cut(int x, int y) {
split(x, y);
ch[y][0] = f[x] = 0;
pushup(y);
}
} using namespace LCT;
struct rec {
int u, v, ed;
bool operator<(const rec &x) {
return ed > x.ed;
}
} e[MAXN];
struct qry {
int x, y, u, v, k;
} q[MAXN];
inline int nde(int x, int y) {
if(!qwq[x][y])qwq[x][y] = ++T;
return qwq[x][y];
}
int main() {
scanf("%d", &n);
while(1) {
scanf("%s", s);
if(s[0] == 'E')break;
++Q;
scanf("%d%d%d%d", &q[Q].x, &q[Q].y, &q[Q].u, &q[Q].v);
int a = nde(q[Q].x, q[Q].y);
int b = nde(q[Q].u, q[Q].v);
if(a > b)a ^= b ^= a ^= b;
if(s[0] == 'O') {
++m;
mp[mkp(a, b)] = m;
e[m].u = a;
e[m].v = b;
q[Q].x = m;
q[Q].k = 1;
} else if(s[0] == 'C') {
q[Q].x = mp[mkp(a, b)];
e[q[Q].x].ed = Q;
q[Q].k = 2;
} else if(s[0] == 'A') {
q[Q].x = a;
q[Q].y = b;
}
}
for(int i = 0; i <= T; ++i)val[i] = inf;
for(int i = 1; i <= m; ++i) {
if(!e[i].ed)val[i + T] = Q + 1, e[i].ed = Q + 1; //删除?不存在的
else val[i + T] = e[i].ed;
}
for(int i = 1; i <= Q; ++i) {
if(q[i].k == 0) {
split(q[i].x, q[i].y);
if(val[minid[q[i].y]] > i && findroot(q[i].x) == findroot(q[i].y))puts("Y");
else puts("N");
} else if(q[i].k == 1) {
int I = q[i].x;
split(e[I].u, e[I].v);
if(findroot(e[I].u) != findroot(e[I].v)) {
link(e[I].u, I + T);
link(e[I].v, I + T);
} else if(val[minid[e[I].v]] < e[I].ed) {
int p = minid[e[I].v];
cut(p, e[p - T].u);
cut(p, e[p - T].v);
val[p] = inf;
link(e[I].u, I + T);
link(e[I].v, I + T);
}
}
}
return 0;
}