求助卡常
查看原帖
求助卡常
589961
steambird楼主2024/11/4 16:20

LCT 做法……有点长(调试输出没删)

#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 = 800004, LN = 800004*4, M = 1e6+4;

/////////////////////////////////////////////////////////////////////
// Link-Cut-Tree Template
/////////////////////////////////////////////////////////////////////


namespace LCT {
	#define lc t[x].ch[0]
	#define rc t[x].ch[1]
	struct node {
		int fa,ch[3],sum,val,lazy;
	} t[LN];
	bool isroot(const int& x) {
		long long g=t[x].fa;
		return t[g].ch[0]!=x&&t[g].ch[1]!=x;
	}
	void pushup(const int& x) {
		t[x].sum=t[x].val^t[lc].sum^t[rc].sum;
	}
	void reverse(const int& x) {
		if(!x)return;
		swap(lc,rc);
		t[x].lazy^=1;
	}
	void pushdown(const int& x) {
		if(t[x].lazy) {
			reverse(lc);
			reverse(rc);
			t[x].lazy=0;
		}
	}
	void push(const int& x) {
		if(!isroot(x))push(t[x].fa);
		pushdown(x);
	}
	void rotate(const int& x) {
		const int y=t[x].fa;
		const int z=t[y].fa;
		const int k=t[y].ch[1]==x;
		if(!isroot(y)) t[z].ch[t[z].ch[1]==y]=x;
		t[x].fa=z;
		t[y].ch[k]=t[x].ch[k^1];
		if(t[x].ch[k^1])t[t[x].ch[k^1]].fa=y;
		t[y].fa=x;
		t[x].ch[k^1]=y;
		pushup(y);
	}
	void splay(const int& x) {
		int y,z;
		push(x);
		while(!isroot(x)) {
			y=t[x].fa,z=t[y].fa;
			if(!isroot(y))
				(t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
			rotate(x);
		}
		pushup(x);
	}
	void access(int x) {
		for(int y=0; x; y=x,x=t[x].fa) {
			splay(x);
			rc=y;
			pushup(x);
		}
	}
	void makeroot(const int& x) {
		access(x);
		splay(x);
		reverse(x);
	}
	void split(const int& x, const int& y) {
		makeroot(x);
		access(y);
		splay(y);
	}
	int findroot(int x) {
		access(x),splay(x);
		while(lc)pushdown(x),x=lc;
		pushdown(x);
		return x;
	}
	void link(const int& x,const int& y) {
		int fx = findroot(x), fy = findroot(y);
		if (fx == fy) return;
		makeroot(x);
		t[x].fa=y;
	}
	void cut(const int& x,const int& y) {
		makeroot(x);
		access(y);
		splay(y);
		if(t[y].ch[0]!=x||rc)return;
		t[x].fa=t[y].ch[0]=0;
		pushup(x);
	}
	int Lca(int x, int y) {
		int p = 0;
		makeroot(findroot(x));
		access(y);
		for (; x; p = x, x = t[x].fa)
			splay(x), rc = p;
		return p;
	}
	
#define Findroot findroot
#define Link link
	
};

/////////////////////////////////////////////////////////////////////
// End of Link-Cut-Tree Template
/////////////////////////////////////////////////////////////////////


struct edge {
	int to, id;
	edge() {
		
	}
	edge(int to) : to(to) {
		
	}
	edge(int to, int id) : to(to), id(id) {
		
	}
};

struct op {
	int type, u, v;
};

op data[M];

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];
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;

bool cmp(const edge &a, const edge &b) {
	return save[a.id] > save[b.id];
}

int src, ct,  lctlca = -1;

int fillup(int l, int r) {
//	cerr << "fillup(" << l << "," << r << "," << "), depth: " << depth[l] << "," << depth[r] << ", timeout: " << enable_when[l] << "," << enable_when[r] << "\n";
	if (depth[l] < depth[lctlca]) l = lctlca;
	if (depth[r] < depth[lctlca]) r = lctlca;
	if (l != r && (enable_when[l] >= ct || enable_when[r] >= ct)) {
		if (depth[l] < depth[r]) swap(l, r);
		if (enable_when[l] < ct) swap(l, r);
		int ft = father[target[l]];
		tarjan.merge(l, src);
		return target[l] = fillup(ft, r);
	} else {
		tarjan.merge(l, src);
		tarjan.merge(r, src);
		return l;
	}
}

inline void edge_worker(int ap, int bp, const int& i) {
	// Skip tree edge.
	if (father[ap] == bp || father[bp] == ap) {
		if ((father[ap] == bp && enable_when[ap] == i) || (father[bp] == ap && enable_when[bp] == i)) {
			if (father[bp] == ap) swap(ap, bp);
			// bp is the father of ap then
			LCT::Link(ap, bp);
			return;
		}
	}
//	cerr << "start fillup" << endl;
	// Can't ensure correctness. has guaranteed that it is not tree-edge.
	src = ap; ct = i; lctlca = LCT::Lca(ap, bp);
	fillup(ap, bp);
//	cerr << endl;
}

priority_queue<edge> pq;
bool operator < (const edge &a, const edge &b) {
	return a.id < b.id;
}

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

// Scan "enable-when" requirements.
void dfs3(int cur, int fa) {
//	cerr << "tree construction " << fa << " -> " << cur << ", enabled at " << enable_when[cur] << endl;
	father[cur] = fa;
	depth[cur] = depth[fa] + 1;
	for (auto &i : gentree[cur]) {
		if (i.to == fa) continue;
		enable_when[i.to] = save[i.id];
		if (save[i.id] > q) LCT::Link(i.to, cur);	// cur is father or i
		dfs3(i.to, cur);
	}
}

map<pair<int, int>, int> ids;

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

void write(int x)
{
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
    return;
}

int main() {

	
//	cin>>n>>m>>q;
	n = read(); m = read(); q = read();
	tarjan.init(n); complete.init(n); gens.init(n);
	for (int i = 1; i <= m; i++) {
//		cin>>ax[i]>>bx[i];
		ax[i] = read(); bx[i] = read();
		graph[ax[i]].push_back(edge(bx[i], i));
		graph[bx[i]].push_back(edge(ax[i], i));
		ids[make_pair(mini(ax[i], bx[i]), maxi(ax[i], bx[i]))] = i;
		save[i] = q+1;
		complete.merge(ax[i], bx[i]);
	}
	for (int i = 1; i <= q; i++) {
//		cin>>data[i].type;
		char ch;
		do {
			ch = getchar();
		} while (ch != 'Z' && ch != 'P');
//		cin>>ch;
		data[i].type = (ch == 'Z' ? 1 : 2);
//		cin>>data[i].u>>data[i].v;
		data[i].u = read(); data[i].v = read();
		if (data[i].type == 1) {
			auto ap = make_pair(mini(data[i].u, data[i].v), maxi(data[i].u, data[i].v));
			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;
				gentree[ax[pt.to]].emplace_back(edge(bx[pt.to], pt.to));
				gentree[bx[pt.to]].emplace_back(edge(ax[pt.to], pt.to));
				cnt++;
//				cerr << "connected " << ax[pt.to] << " -> " << bx[pt.to] << " with time " << save[pt.to] << endl;
				gens.merge(ax[pt.to], bx[pt.to]);
			}
			while (!pq.empty()) pq.pop();
			dfs3(i, i);
		}
		target[i] = i;
	}
	for (int i = 1; i <= n; i++) {
//		cerr << "enable time for " << i << " is " << enable_when[i] << endl;
		for (auto &j : graph[i]) {
			if (save[j.id] > q) edge_worker(i, j.to, q+1);
		}
	}
	for (int i = q; i >= 1; i--) {
//		cerr << "==============================\n";
		if (data[i].type ^ 1) {
			ans[i] = (tarjan.query(data[i].u) == tarjan.query(data[i].v) ? true : false);
		} else {
			// Query through
//			int ap = ax[data[i].u], bp = bx[data[i].u];
			int ap = data[i].u, bp = data[i].v;
			edge_worker(ap, bp, i);
		}
	}
	for (int i = 1; i <= q; i++) {
		if (data[i].type == 1) continue;
//		cout << (ans[i] ? "TAK\n" : "NIE\n");
		if (ans[i]) puts("TAK");
		else puts("NIE");
	}
	

	return 0;
}
2024/11/4 16:20
加载中...