steambird @ 2024-11-04 17:31:16
rt,WA on #1000 ~ #40000 行,
#include <bits/stdc++.h>
using namespace std;
inline void train() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
inline int maxi(int a, int b) {
return a > b ? a : b;
}
inline int mini(int a, int b) {
return a < b ? a : b;
}
constexpr int N = 5e5+4, LN = 800004*4, M = 5e5+4;
vector<int> tree[N];
struct edge {
int to, id;
edge() {
}
edge(int to) : to(to) {
}
edge(int to, int id) : to(to), id(id) {
}
};
priority_queue<edge> pq;
bool operator < (const edge &a, const edge &b) {
return a.id < b.id;
}
vector<edge> graph[N], gentree[N];
int n, m, q, tid, father[N], ax[M], bx[M], save[M], depth[N], enable_when[N], target[N];
int cover[N], fas[N][20];
char otype[N];
int us[N], vs[N];
bool ans[N];
bool vis[N];
struct dset {
dset() {
}
int fa[N], sz[N];
inline void init(const int& n) {
for (int i = 1; i <= n; i++) {
fa[i] = i;
sz[i] = 1;
}
}
int query(const int& x) {
return x == fa[x] ? x : fa[x] = query(fa[x]);
}
inline void merge(const int& a, const int& b) {
int qa = query(a), qb = query(b);
if (qa == qb) return;
if (sz[qa] < sz[qb]) swap(qa, qb);
fa[qb] = qa;
sz[qa] += sz[qb];
}
};
dset tarjan, complete, gens;
void dfs(int cur, int fa) {
// cerr << fa << " -> " << cur << endl;
depth[cur] = depth[fa] + 1;
father[cur] = fa;
for (auto &i : tree[cur]) {
if (i == fa) continue;
dfs(i, cur);
}
}
int lca(int a, int b) {
if (depth[a] < depth[b]) swap(a, b);
int diff = depth[a] - depth[b];
for (int i = 1<<19, bs = 19; i >= 1; i >>= 1, bs--) {
if (diff & i) a = fas[a][bs];
}
if (a == b) return a;
while (father[a] != father[b]) {
int step = 19;
for (; step >= 0 && fas[a][step] == fas[b][step]; step--);
if (step < 0) return father[a];
a = fas[a][step];
b = fas[b][step];
}
return father[a];
}
void icover(int a, int l, int s) {
int x = a;
while (depth[a] > depth[l]) {
cover[a]++;
if (cover[a] > 1) tarjan.merge(a, l);
// cerr << "Executed to " << a << ", covering " << cover[a] << endl;
a = father[target[a]];
}
while (depth[x] > depth[l]) {
int tmp = father[target[x]];
if (cover[x] > 1) target[x] = a;
x = tmp;
}
}
void covering(int a, int b) {
int l = lca(a, b);
// cerr << "Covering " << a << " and " << b << ", LCA = " << l << endl;
icover(a, l, a);
// cerr << "===\n";
icover(b, l, a);
// cerr << endl;
}
set<pair<int, int> > edges;
map<pair<int, int>, int> ids;
void dfs1(int cur, int fa) {
vis[cur] = true;
for (auto &i : graph[cur]) {
pq.push(edge(i.id, save[i.id]));
if (vis[i.to]) continue;
dfs1(i.to, cur);
}
}
int main() {
train();
cin>>n>>m>>q;
tarjan.init(n); complete.init(n); gens.init(n);
for (int i = 1; i <= m; i++) {
cin>>ax[i]>>bx[i];
int a = ax[i], b = bx[i];
graph[ax[i]].push_back(edge(bx[i], i));
graph[bx[i]].push_back(edge(ax[i], i));
auto ap = make_pair(mini(a,b),maxi(a,b));
edges.insert(ap);
save[i] = q+1;
ids[ap] = i;
complete.merge(ax[i], bx[i]);
}
for (int i = 1; i <= q; i++) {
cin>>otype[i]>>us[i]>>vs[i];
int a = us[i], b = vs[i];
if (otype[i] == 'Z') {
auto ap = make_pair(mini(a,b),maxi(a,b));
edges.erase(ap);
save[ids[ap]] = i;
}
}
for (int i = 1; i <= n; i++) {
if (complete.query(i) == i) {
// Generate a tree:
dfs1(i, i);
// cerr << "Construct tree for " << i << endl;
int cnt = 0;
while ((cnt <= complete.sz[i]) && (!pq.empty())) {
edge pt = pq.top();
pq.pop();
if (gens.query(ax[pt.to]) == gens.query(bx[pt.to])) continue;
tree[ax[pt.to]].emplace_back(bx[pt.to]);
tree[bx[pt.to]].emplace_back(ax[pt.to]);
// cerr << ax[pt.to] << " <-> " << bx[pt.to] << endl;
cnt++;
gens.merge(ax[pt.to], bx[pt.to]);
}
while (!pq.empty()) pq.pop();
dfs(i, i);
}
target[i] = i;
}
for (int i = 1; i <= n; i++) {
target[i] = i;
fas[i][0] = father[i];
}
for (int step = 1; step < 20; step++) {
for (int i = 1; i <= n; i++) fas[i][step] = fas[fas[i][step-1]][step-1];
}
for (auto &i : edges) covering(i.first, i.second);
for (int i = q; i >= 1; i--) {
switch (otype[i]) {
case 'Z':
// Do the cover
covering(us[i], vs[i]);
break;
case 'P':
ans[i] = (tarjan.query(us[i]) == tarjan.query(vs[i]));
break;
}
}
for (int i = 1; i <= q; i++) {
if (otype[i] == 'P') {
if (ans[i]) cout<<"TAK\n";
else cout<<"NIE\n";
}
}
cout<<flush;
return 0;
}