3251: 树上三角形

来源:互联网 发布:中国证券软件下载 编辑:程序博客网 时间:2024/05/17 23:34

题目链接

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

题解:看到题目果断开始想数据结构,感觉要上lct?蒟蒻表示不会……膜了一发题解后。考虑这样一个问题:有一个数列,数列中的数满足题目条件,那么最优就是斐波那契数列,在2^31次方中斐波那契数列只有不到50项……路径长度大于50直接输出,小于就暴力排序搞一下,最坏O(q*50*log50)

我的收获:猜测答案增长速度(例如指数型)

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm> using namespace stdconst int M=100005int n,q,t;int head[M],dep[M],fa[M],w[M],st[105]; struct edge{int to,nex;}e[M*4]; void add(int u,int v){e[t].to=v,e[t].nex=head[u],head[u]=t++;} void dfs(int x){    for(int i=head[x];i!=-1;i=e[i].nex){        int v=e[i].to;        if(v!=fa[x]) fa[v]=x,dep[v]=dep[x]+1,dfs(v);    }} bool check(int x,int y){    int top=0,z;    while(top<47&&x!=y)    {        if(dep[x]<dep[y]) z=x,x=y,y=z;        st[++top]=w[x],x=fa[x];    }    st[++top]=w[x];    if(top>=47) return true;    sort(st+1,st+1+top);    for(int i=3;i<=top;i++)        if(st[i-1]>st[i]-st[i-2])//用减法防止爆int             return true;    return false;} void work(){    int x,y,opt;    while(q--)    {        scanf("%d%d%d",&opt,&x,&y);        if(!opt) puts(check(x,y)?"Y":"N");        else w[x]=y;    }} void init(){    cin>>n>>q;t=0;    int x,y;memset(head,-1,sizeof(head));    for(int i=1;i<=n;i++)        scanf("%d",&w[i]);    for(int i=1;i<n;i++)        scanf("%d%d",&x,&y),add(x,y),add(y,x);    dfs(1);} int main(){    init();    work();    return 0; } 
原创粉丝点击