bzoj3251: 树上三角形(思维题)
神tmWA了8发调了20min才发现输出没回车T T...
首先考虑一段什么样的序列才会是N... 显然最长的形式就是斐波那契,前两数之和等于第三数之和,这样就无法组成三角形并且序列最长。可以发现在int范围内斐波那契数列不会超过50个,所以如果这段路径上节点数超过50个直接输出Y,否则把50个数拉出来排序暴力找是否有三角形就好了。


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010;
struct poi{int too, pre;}e[maxn<<1];
int n, q, ty, x, y, cnt, tot;
int a[maxn], d[maxn], fa[maxn], last[maxn], st[maxn];
void read(int &k)
{
int f=1; k=0; char c=getchar();
while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
k*=f;
}
inline void add(int x, int y){e[++tot]=(poi){y, last[x]}; last[x]=tot;}
void dfs(int x)
{
d[x]=d[fa[x]]+1;
for(int i=last[x], too;i;i=e[i].pre)
fa[too=e[i].too]=x, dfs(too);
}
inline bool query(int x, int y)
{
int cnt=0;
while(cnt<50)
{
if(d[x]<d[y]) swap(x, y);
st[++cnt]=a[x];
if(x==y) break; x=fa[x];
}
if(cnt>=50) return 1;
sort(st+1, st+1+cnt);
for(int i=1;i<=cnt-2;i++)
if((ll)st[i]+st[i+1]>st[i+2]) return 1;
return 0;
}
int main()
{
read(n); read(q);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<n;i++) read(x), read(y), add(x, y);
dfs(1);
for(int i=1;i<=q;i++)
{
read(ty); read(x); read(y);
if(!ty) printf("%s\n", query(x, y)?"Y":"N");
else a[x]=y;
}
}View Code