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

浙公网安备 33010602011771号