【刷题笔记】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;
}

浙公网安备 33010602011771号