【刷题笔记】p10799

思路

正难则反,考虑什么时候无法组成三角形。
我们将 \(a\) 数组递增排序(记录三角形的边权),当 \(a_{i-2}+a_{i-1}\le a_i\) 时无法组成,最小的时候为一个斐波那契数列。
发现 \(f_{46}>10^9\),所以 \(n\ge46\) 时一定是可以组成的,在其余情况下暴力在树上跳就可以了。
那么如何在路径上异或,单点查询呢?可以用树上差分,再用 dfn 序搞个树状数组就可以了。
完结撒花 AWA

code

#include<bits/stdc++.h>
#define N 100010
#define lowbit(x) x & (-x)
using namespace std;
int dfn[N], n, q, a[N], head[N], cnt = 0;
int tim = 0, siz[N], d[N], f[N][60];
int t[N], dep[N], s[N], num[N];
struct edge{
	int to, next;
}e[N << 1];
void add(int x, int y){
	e[++cnt].next = head[x];
	e[cnt].to = y;
	head[x] = cnt;
}
void update(int x, int k){
	x = dfn[x];
	while(x <= n){
		t[x] ^= k;
		x += lowbit(x);
	}
}
int query(int x){
	int sum = 0;
	while(x){
		sum ^= t[x];
		x -= lowbit(x);
	}
	return sum;
}
void dfs(int u, int fa){
	dfn[u] = ++tim, siz[u] = 1, d[u] = a[u];
	f[u][0] = fa, dep[u] = dep[fa] + 1;
	for(int i = 1; i <= 30; i++) f[u][i] = f[f[u][i - 1]][i - 1];
	for(int i = head[u]; i; i = e[i].next){
		int v = e[i].to;
		if(v == fa) continue;
		dfs(v, u); 
		siz[u] += siz[v], d[u] ^= a[v];
	}
}
int getval(int u){
	return query(dfn[u] + siz[u] - 1) ^ (dfn[u] > 1 ? query(dfn[u] - 1) : 0);
}
int lca(int x, int y){
	if(dep[x] < dep[y]) swap(x, y);
	int len = dep[x] - dep[y];
	for(int i = 0; i <= 25; i++){
		if(len & 1) x = f[x][i];
		len >>= 1;
	}
	if(x == y) return x;
	for(int i = 25; i >= 0; i--){
		if(f[x][i] == f[y][i]) continue;
		x = f[x][i], y = f[y][i];
	}
	return f[x][0];
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1; i < n; i++){
		int x, y; cin >> x >> y;
		add(x, y), add(y, x);
	}
	dfs(1, 0);
	for(int i = 1; i <= n; i++) update(i, d[i]);
	while(q--){
		int s, x, y, w; cin >> s;
		if(s == 1){
			cin >> x >> y >> w;
			int _lca = lca(x, y);
			update(x, w), update(y, w), update(_lca, w);
			if(f[_lca][0]) update(f[_lca][0], w);
		}
		else{
			cin >> x >> y;
			int _lca = lca(x, y);
			int tot = dep[x] + dep[y] - 2 * dep[_lca] + 1;
			if(tot > 46) cout << 1;
			else{
				tot = 0;
				while(x != _lca )
					num[++tot] = getval(x), x = f[x][0];
				while(y != _lca )
					num[++tot] = getval(y), y = f[y][0];
				num[++tot] = getval(_lca);
				sort(num + 1, num + tot + 1);
				if(tot < 3) cout << 0;
				else{
					bool flag = 0;
					for(int j = 2; j < tot; j++){
						if(num[j] > num[j + 1] - num[j - 1]){
							flag = 1; break;
						}
					}
					if(flag) cout << 1;
					else cout << 0;
				}
			}
		}
	}
	return 0;
} 
posted @ 2025-05-06 22:21  GuoSN0410  阅读(22)  评论(0)    收藏  举报