题意
判断树上路径上所有权值是否存在3个权值能构成一个三角形。多次询问,单点修改。
题解
若路径上有两点的点权为x,y,则若有个点z且z>abs(x-y)且z<x+y,则可以构成三角形
类似斐波那契数列1 2 3 5 8 13 …
发现最好情况下int范围只有不到50个点满足无法构成三角形
那么只要路径点超过50个直接输出Y,否则暴力
CODE
#pragma GCC optimize ("O2")
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int n, q, fa[MAXN], v[MAXN], dep[MAXN];
int a[MAXN];
vector<int>G[MAXN];
void dfs(int u) {
dep[u] = dep[fa[u]] + 1;
for(int i = G[u].size()-1; i >= 0; --i)
dfs(G[u][i]);
}
int main () {
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; ++i) scanf("%d", &v[i]);
for(int i = 1, x, y; i < n; ++i) scanf("%d%d", &x, &y), fa[y] = x, G[x].push_back(y);
dfs(1);
int op, x, y;
while(q--) {
scanf("%d%d%d", &op, &x, &y);
if(op == 1) v[x] = y;
else {
int top = 0;
while(top < 50 && x != y) {
if(dep[x] < dep[y]) swap(x, y);
a[++top] = v[x]; x = fa[x];
}
a[++top] = v[x];
if(top >= 50) puts("Y");
else {
sort(a + 1, a + top + 1);
bool flg = 0;
for(int i = 1; i+2 <= top; ++i)
if(1ll*a[i]+a[i+1]>a[i+2]) { flg = 1; break; }
puts(flg ? "Y" : "N");
}
}
}
}