SHOI2008 堵塞的交通题解

算法

这题中有增边,去边和查连通性操作,动态图连通性直接想到线段树分治

具体方法

可以考虑对每个点进行编号(便于操作,反正也就\(2 \times N\)个点),接着就是常规的线段树分治了。
这里注意记录最后出现的边版本。

代码

#include <iostream>
#include <cstring>
#include <stack>
#include <unordered_map>
#include <vector>
#include <algorithm>

using namespace std;

const int N = 2e5+2;
const int M = 3e5+1;
int ID[3][N];
class DSU{
private:
	int fa[N];
	int dep[N];
	stack<pair<int, int> >sta;
public:
	inline int size(){
		return sta.size();
	}
	inline void init(int n){
		for(int i = 1; i <= n; i++)
			fa[i] = i, dep[i] = 0;
		while(!sta.empty())
			sta.pop();
	}
	inline int find(int x){
		if(fa[x] == x)
			return x;
		return find(fa[x]);
	}
	inline bool check(int x, int y){
		return find(x) == find(y);
	}
	inline void join(int x, int y){
		x = find(x);
		y = find(y);
		if(x == y)
			return;	
		if(dep[x] > dep[y])
			swap(x, y);
		if(dep[x] == dep[y])
			dep[y]++;
		fa[x] = y;
		sta.push(make_pair(x, y));
	}
	inline void undo(int x){
		while(sta.size() > x){
			int x = sta.top().first;
			int y = sta.top().second;
			sta.pop();
			if(dep[y] == dep[x]+1)
				dep[y]--;
			fa[x] = x;
		}
	}
};
DSU UN;
typedef struct{
	int tp;
	int x, y;
	inline bool get(){
		string s;
		cin >> s;
		if(s[0] == 'E')
			return false;
		if(s[0] == 'C')
			tp = 0;
		if(s[0] == 'O')
			tp = 1;
		if(s[0] == 'A')
			tp = 2;
		int r, c;
		scanf("%d%d", &r, &c);
		x = ID[r][c];
		scanf("%d%d", &r, &c);
		y = ID[r][c];
		return true;
	}
}OPT;
OPT a[N];
bool ans[N];
vector<OPT>tree[N<<2];
inline int lchild(int x){return x<<1;}
inline int rchild(int x){return x<<1|1;}
inline void modify(int p, int pl, int pr, int l, int r, int x){
	if(pl >= l && pr <= r){
		tree[p].push_back(a[x]);
		// cout << pl << " " << pr << endl;
		return;
	}
	int mid = (pl+pr) >> 1;
	if(mid >= l)
		modify(lchild(p), pl, mid, l, r, x);
	if(mid < r)
		modify(rchild(p), mid+1, pr, l, r, x);
	return;
}
inline void dfs(int p, int pl, int pr){
	int tmp = UN.size();
	for(auto i : tree[p])
		UN.join(i.x, i.y);
	if(pl == pr){
		if(a[pl].tp == 2)
			puts(UN.check(a[pl].x, a[pl].y) ? "Y" : "N");
		UN.undo(tmp); 
		return;
	}
	int mid = (pl+pr) >> 1;
	dfs(lchild(p), pl, mid);
	dfs(rchild(p), mid+1, pr);
	UN.undo(tmp);
	
	return;
}
unordered_map<int, int>st[N];
unordered_map<int, int>lst[N];
int main(){
	int n;
	scanf("%d", &n);
	UN.init(2*n);
	int cnt = 0;
	for(int i = 1; i <= 2; i++)
		for(int j = 1; j <= n; j++)
			ID[i][j] = (i-1)*n+j;
	while(a[++cnt].get());
	cnt--;
	for(int i = 1; i <= cnt; i++){
		if(a[i].tp == 0 && st[a[i].x][a[i].y]){
			modify(1, 1, cnt, st[a[i].x][a[i].y], i-1, i);
			st[a[i].x][a[i].y] = st[a[i].y][a[i].x] = 0;
		}
		if(a[i].tp == 1 && !st[a[i].x][a[i].y]){
			st[a[i].x][a[i].y] = st[a[i].y][a[i].x] = i;
			lst[a[i].x][a[i].y] = lst[a[i].x][a[i].y] = i;
		}
	}
	for(int i = 1; i <= cnt; i++)
		if(st[a[i].x][a[i].y] && a[i].tp == 1){
			st[a[i].x][a[i].y] = st[a[i].y][a[i].x] = 0;
			modify(1, 1, cnt, lst[a[i].x][a[i].y], cnt, i);
		}
	dfs(1, 1, cnt);
	return 0;
}
posted @ 2024-05-28 11:24  HurryCine  阅读(12)  评论(0)    收藏  举报