zoukankan      html  css  js  c++  java
  • BZOJ-3251 树上三角形

    给定一大小为n的有点权树,每次询问一对点(u,v),问是否能在u到v的简单路径上取三个点权,以这三个权值为边
    长构成一个三角形。同时还支持单点修改。
     
    Input
    第一行两个整数n、q表示树的点数和操作数
    第二行n个整数表示n个点的点权
    以下n-1行,每行2个整数a、b,表示a是b的父亲(以1为根的情况下)
    以下q行,每行3个整数t、a、b
    若t=0,则询问(a,b)
    若t=1,则将点a的点权修改为b
     
    n,q<=100000,点权范围[1,2^31-1] 
     
    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

    题目链接

     分析 

    如果三个点权要构成三角形,那么需要x+y>z。类似于斐波那契数列,可以发现,在int范围里,fibonacci数只有50个左右。那么只要简单路径的节点数超过50,必然能构成三角形。而低于50个的话就暴力遍历,排序,检查是否存在s[i]+s[i+1]>s[i+2]。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include <queue>
    #include <vector>
    #include<bitset>
    #include<map>
    #include<deque>
    using namespace std;
    typedef long long LL;
    const int maxn = 5e4+5;
    const int mod = 77200211+233;
    typedef pair<int,int> pii;
    #define X first
    #define Y second
    #define pb push_back
    //#define mp make_pair
    #define ms(a,b) memset(a,b,sizeof(a))
    const int inf = 0x3f3f3f3f;
    #define lson l,m,2*rt
    #define rson m+1,r,2*rt+1
    typedef long long ll;
    #define N 100010
    
    struct use{
        int st,en;
    }e[N*2];
    int cnt,point[N],Next[N*2],top,s[N],v[N],n,x,y,q,kind,deep[N],fa[N];
    void add(int x,int y){
        Next[++cnt]=point[x];
        point[x]=cnt;
        e[cnt].st=x;
        e[cnt].en=y;
    }
    void dfs(int x){
        for (int i=point[x];i;i=Next[i])
            if (e[i].en!=fa[x]){
                fa[e[i].en]=x;
                deep[e[i].en]=deep[x]+1;
                dfs(e[i].en);
            }
    }
    void solve(int x,int y){
       int t=0;
       while (x!=y&&t<50){
         if (deep[x]>deep[y]) s[++t]=v[x],x=fa[x];
         else s[++t]=v[y],y=fa[y];
       }
       s[++t]=v[x];
       if (t>=50){
            printf("Y
    ");
            return;
        }
       sort(s+1,s+t+1);
       for (int i=1;i<=t-2;i++)
            if((long long)s[i]+s[i+1]>s[i+2]){
                printf("Y
    ");
                return;
            }
       printf("N
    ");
    }
    int main(){
      scanf("%d%d",&n,&q);
      for (int i=1;i<=n;i++) scanf("%d",&v[i]);
      for (int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
      dfs(1);
      for (int i=1;i<=q;i++){
        scanf("%d%d%d",&kind,&x,&y);
        if (kind==1){
            v[x]=y;
            continue;
        }
        solve(x,y);
      }
      return 0;
    }
  • 相关阅读:
    如何查看一个表的块使用状况
    esp8266烧录Html文件,实现内置网页控制设备!
    python一键电影搜索与下载
    基于 Vue BootStrap的迷你Chrome插件
    SpringBoot之自定义验证码
    iOS 图片部分模糊,类似于美图秀秀
    python实现的电影票房数据可视化
    坦克大战-C语言-详注版
    微信小程序-自定义底部导航
    微信小程序--搜索关键词高亮
  • 原文地址:https://www.cnblogs.com/fht-litost/p/8719586.html
Copyright © 2011-2022 走看看