[BZOJ3251]树上三角形

Description
给定一大小为n的有点权树,每次询问一对点(u,v),问是否能在u到v的简单路径上取三个点权,以这三个权值为边长构成一个三角形。同时还支持单点修改。

Input
第一行两个整数n、q表示树的点数和操作数
第二行n个整数表示n个点的点权
以下n-1行,每行2个整数a、b,表示a是b的父亲(以1为根的情况下)
以下q行,每行3个整数t、a、b
若t=0,则询问(a,b)
若t=1,则将点a的点权修改为b
n,q<=100000,点权范围[1,2^31-1]

Output
对每个询问输出一行表示答案,“Y”表示有解,“N”表示无解。

Sample Input
5 5
1 2 3 4 5
1 2
2 3
3 4
1 5
0 1 3
0 4 5
1 1 4
0 2 5
0 2 3

Sample Output
N
Y
Y
N


这题直接暴力!!!

考虑一下不能凑出三角形的木棍长度排列

1,2,3,5,8,11,...

就是Fibonacci数列,所以路径长度>50就直接输出Y,否则暴力判断。。。

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
	int x=0,f=1;char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline int read(){
	int x=0,f=1;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)    putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int N=1e5;
vector<ui>vec;
int v[N+10];
struct S1{
	int pre[(N<<1)+10],now[N+10],child[(N<<1)+10],tot;
	int deep[N+10],fa[N+10],Rem[N+10],top[N+10],size[N+10];
	void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
	void insert(int x,int y){join(x,y),join(y,x);}
	void dfs(int x){
		deep[x]=deep[fa[x]]+1,size[x]=1;
		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
			if (son==fa[x])	continue;
			fa[son]=x,dfs(son);
			size[x]+=size[son];
			if (size[Rem[x]]<size[son])	Rem[x]=son;
		}
	}
	void build(int x){
		if (!x)	return;
		top[x]=Rem[fa[x]]==x?top[fa[x]]:x;
		build(Rem[x]);
		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
			if (son==fa[x]||son==Rem[x])	continue;
			build(son);
		}
	}
	int Lca(int x,int y){
		while (top[x]!=top[y]){
			if (deep[top[x]]<deep[top[y]])	swap(x,y);
			x=fa[top[x]];
		}
		return deep[x]<deep[y]?x:y;
	}
	bool work(int x,int y){
		int lca=Lca(x,y);
		if (deep[x]+deep[y]-2*deep[lca]+1>50)	return 1;
		vec.clear(); vec.push_back(v[lca]);
		for (;x!=lca;x=fa[x])	vec.push_back(v[x]);
		for (;y!=lca;y=fa[y])	vec.push_back(v[y]);
		sort(vec.begin(),vec.end());
		for (vector<ui>::iterator i=vec.begin();i!=vec.end();i++)
			for (vector<ui>::iterator j=i+1;j!=vec.end();j++)
				for (vector<ui>::iterator k=j+1;k!=vec.end();k++)
					if (*k<*j+*i)	return 1;
		return 0;		
	}
}HLD;//Heavy Light Decomposition
int main(){
	int n=read(),m=read();
	for (int i=1;i<=n;i++)	v[i]=read();
	for (int i=1;i<n;i++){
		int x=read(),y=read();
		HLD.insert(x,y);
	}
	HLD.dfs(1),HLD.build(1);
	for (int i=1;i<=m;i++){
		int type=read(),x=read(),y=read();
		if (type==0)	printf(HLD.work(x,y)?"Y
":"N
");
		if (type==1)	v[x]=y;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Wolfycz/p/9994289.html