bzoj3251: 树上三角形(思维题)

神tmWA了8发调了20min才发现输出没回车T T...

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

bzoj3251: 树上三角形(思维题)bzoj3251: 树上三角形(思维题)
#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