BZOJ 3251 树上三角形 (暴力) 题意 题解 CODE

判断树上路径上所有权值是否存在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");
			}
		}
	}
}