版权声明:辛辛苦苦码字,你们转载的时候记得告诉我 https://blog.csdn.net/dxyinme/article/details/83661136
Time Limit: 10 Sec
Memory Limit: 128 MB
Description
给定一大小为
的有点权树,每次询问一对点
,问是否能在
到
的简单路径上取三个点权,以这三个权值为边长构成一个三角形。同时还支持单点修改。
Input
第一行两个整数
表示树的点数和操作数
第二行
个整数表示
个点的点权
以下
行,每行2个整数
,表示a是b的父亲(以1为根的情况下)
以下
行,每行3个整数
若
,则询问
若
,则将点
的点权修改为
,点权范围
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
题解:
以前应该是在FJ省选做过这题…
对于询问,lca查询两点之间的路径长度,由于能使得他们无法组成三角形的路径上的点权序列
排序后要满足
,所以点权序列增长率>=斐波那契数列,但是斐波那契数列在第
位的时候就超出
,那么若路径长度>48的时候就直接输出"Y",否则将路径序列弄下来排序验证一下。
对于修改就直接暴力修改。
#include<bits/stdc++.h>
#define LiangJiaJun main
using namespace std;
int n,q;
int ne,h[100004];
int fa[100004][24],depth[100004];
struct edge{
int to,nt;
}e[300004];
void add(int u,int v){
e[++ne].to=v;
e[ne].nt=h[u];
h[u]=ne;
}
int a[100004],g[104],cnt;
void dfs(int x){
for(int i=1;fa[fa[x][i-1]][i-1];i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
}
for(int i=h[x];i;i=e[i].nt){
if(depth[e[i].to])continue;
depth[e[i].to]=depth[x]+1;
fa[e[i].to][0]=x;
dfs(e[i].to);
}
}
int lca(int u,int v){
if(depth[u]<depth[v])swap(u,v);
int dva=(depth[u]-depth[v]);
for(int i=0;i<=20;i++){
if(dva&(1<<i))u=fa[u][i];
}
for(int i=20;i>=0;i--){
if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
}
if(u==v)return u;
else return fa[u][0];
}
bool check(int x,int fxy,int y){
cnt=0;
while(x!=fxy){
g[++cnt]=a[x];
x=fa[x][0];
}
while(y!=fxy){
g[++cnt]=a[y];
y=fa[y][0];
}
g[++cnt]=a[fxy];
sort(g+1,g+cnt+1);
for(int i=1;i+2<=cnt;i++){
if(1LL*g[i]+1LL*g[i+1]>1LL*g[i+2])return 1;
}
return 0;
}
int w33ha(){
ne=0;
memset(h,0,sizeof(h));
memset(fa,0,sizeof(fa));
memset(depth,0,sizeof(depth));
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
depth[1]=1;
dfs(1);
while(q--){
int t,x,y;
scanf("%d%d%d",&t,&x,&y);
if(t==0){
int fxy=lca(x,y);
if(depth[x]+depth[y]-(depth[fxy]<<1)>48){
puts("Y");
}
else{
if(check(x,fxy,y))puts("Y");
else puts("N");
}
}
if(t==1){
a[x]=y;
}
}
return 0;
}
int LiangJiaJun(){
while(scanf("%d%d",&n,&q)!=EOF)w33ha();
return 0;
}