3251: 树上三角形

题目链接

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

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

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

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> 
using namespace std;
 
const int M=100005;
 
int 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; 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值