Yandex.Algorithm 2011: Finals E 树链剖分+思维

代码细节太多

思路

先求出 一颗生成树 如果距离为奇数 那就满足 这一过程可以用lca 求解
其他情况下 如果a到b的路径上有一条边属于奇环 那么也符合
那么我们已经清楚如何取求解 剩下就是取维护每条边是否在 奇环上
可以 用差分 但是 这题因为要用到lca 就直接树链剖分维护了

#include 
using namespace  std;
//#define  int long long
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define pb  push_back
#define inf 1<<62
#define endl "\n"
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define de_bug(x) cerr << #x << "=" << x << endl
#define all(a) a.begin(),a.end()
#define IOS   std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define  fer(i,a,b)  for(int i=a;i<=b;i++)
#define  der(i,a,b)  for(int i=a;i>=b;i--)
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int n, m , k;

int id[N];
int top[N], fa[N], f[N], d[N], son[N], siz[N];
vi g[N];
int tot;

struct node {
	int l, r;
	int tag, sum;
} tr[N * 4];

void push_up(int i) {
	tr[i].sum = tr[i * 2].sum + tr[i * 2 + 1].sum;
}
/*void push_down(int i) {
	if(tr[i].tag) {
		tr[i * 2].tag = tr[i].tag;
		tr[i * 2 + 1].tag = tr[i].tag;
		tr[i * 2].sum += tr[i].tag * (tr[i * 2].r - tr[i * 2].l + 1);
		tr[i * 2 + 1].sum += tr[i].tag * (tr[i * 2 + 1].r - tr[i * 2 + 1].l + 1);
	}
	tr[i].tag = 0;
}*/

void pushdown(int i) {
	//int mid = (tr[i].r - tr[i].l) >> 1;
	if(tr[i].sum == (tr[i].r - tr[i].l + 1)) {
		tr[i * 2].sum = tr[i * 2].r - tr[i * 2].l + 1;
		tr[i * 2 + 1].sum = tr[i * 2 + 1].r - tr[i * 2 + 1].l + 1;
	}
}

void build(int i, int l, int r) {
	tr[i] = {l, r, 0, 0};
	if(l == r) {
		return ;
	}
	int mid = (l + r) >> 1;
	build(i * 2, l, mid);
	build(i * 2 + 1, mid + 1, r);
}
void  change(int i, int l, int r, int val) {
	if(l <= tr[i].l && tr[i].r <= r) {
		//	tr[i].tag += val;
		tr[i].sum = tr[i].r - tr[i].l + 1;
		return ;
	}
	pushdown(i);
	int mid = (tr[i].l + tr[i].r) >> 1;
	if(l <= mid) change(i * 2, l, r, val);
	if(r > mid)change(i * 2 + 1, l, r, val);
	push_up(i);
}
int query(int i, int l, int r) {
	if(l <= tr[i].l && tr[i].r <= r) {
		return tr[i].sum;
	}
	int mid = (tr[i].l + tr[i].r) >> 1;
	pushdown(i);
	int ans = 0;
	if(l <= mid) ans += query(i * 2, l, r);
	if(r > mid) ans += query(i * 2 + 1, l, r);
	return ans;
}

int  qry(int x, int y) {
	int cnt = 0;
	while(top[x] != top[y]) {
		if(d[top[x]] < d[top[y]])swap(x, y);
		cnt += query(1, id[top[x]], id[x]);
		x = f[top[x]];
	}
	if(d[y] < d[x]) swap(x, y);
	cnt += query(1, id[x], id[y]);
	return cnt;
}

void upd(int x, int y) {
	//if(x==5&&y==7)cout<<"/"<
	while(top[x] != top[y]) {
		if(d[top[x]] < d[top[y]])swap(x, y);
		change(1, id[top[x]], id[x], 1);
		x = f[top[x]];
	}
	if(d[x] > d[y])swap(x, y);
	change(1, id[son[x]], id[y], 1);
}


void dfs1(int u, int fa) {
	d[u] = d[fa] + 1;
	f[u] = fa;
	siz[u] = 1;
	int ma = -1;
	for(auto v : g[u]) {
		if(d[v])continue;
		dfs1(v, u);
		siz[u] += siz[v];
		if(ma < siz[v]) {
			son[u] = v, ma = siz[v];
		}
	}
}
void dfs2(int u, int ff) {
	id[u] = ++tot;
	top[u] = ff;
	if(!son[u])return;
	dfs2(son[u], ff);
	for(auto v : g[u]) {
		if(v != son[u] && d[v] > d[u] && f[v] == u)dfs2(v, v);
	}
}
void dfs3(int u) {
	for(auto v : g[u]) {
		if(v == f[u])continue;
		if(f[v] == u)dfs3(v);
		else  if( d[v] > d[u] && ( !((d[u] - d[v]) & 1) )) upd(v, u);
	}
}
void dfs4(int u) {
	for(auto v : g[u]) {
		if(v == f[u])continue;
		if(f[v] == u)dfs4(v);
		else if(d[v] > d[u])continue;
		else if( (d[u] - d[v]) & 1) {
			if(qry(v, u) - query(1, id[v], id[v]) > 0 ) {
				upd(v, u);
			}
		}
	}
}
int lca(int x, int y) {
	while(top[x] != top[y]) {
		if(d[top[x]] < d[top[y]])swap(x, y);
		x = f[top[x]];
	}
	return d[x] < d[y] ? x : y;
}
int get_(int a, int b) {
	return d[a] + d[b] - 2 * d[lca(a, b)];
}

int find1(int x) {
	return fa[x] == x ? x : fa[x] = find1(fa[x]);
}
void merge(int a, int b) {
	int x = find1(a);
	int y = find1(b);
	if(x == y)return ;
	fa[x] = y;
}
void solve() {
	cin >> n >> m;
	fer(i, 1, n) {
		fa[i] = i;
	}
	fer(i, 1, m) {
		int a, b;
		cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
		merge(a, b);
	}
	build(1, 1, n);
	fer(i, 1, n) {
		if(!d[i]) {
			dfs1(i, 0);
			dfs2(i, i);
			dfs3(i);
			dfs4(i);
		}
	}
	int q;
	cin >> q;
	fer(i, 1, q) {
		int a, b;
		cin >> a >> b;
		int LCA = lca(a, b);
		if(find1(a) != find1(b))puts("No");
		else {
			if(get_(a, b) & 1)puts("Yes");
			else if(qry(a, b) - query(1, id[LCA], id[LCA]) > 0) {
				puts("Yes");
			} else puts("No");
		}
	}
}
int main() {
	IOS;
	int _ = 1;
	//cin>>_;
	while( _-- )
		solve();
}


你可能感兴趣的:(数据结构,思维,c++,算法,图论)