[BZOJ3251]樹上三角形
阿新 • • 發佈:2018-12-02
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;
}