zoukankan      html  css  js  c++  java
  • BZOJ 3251 树上三角形:LCA【构成三角形的结论】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3251

    题意:

      给你一棵树,n个节点,每个点的权值为w[i]。

      接下来有m个形如(p,a,b)的操作:

        (1)p == 0:

          问你在从a到b的路径上,有没有三个点满足:它们的权值大小可以构成三角形。

          如果有,输出'Y',否则输出'N'。

        (2)p == 1:

          将点a的权值w[a]改为b。

    题解:

      首先考虑一个结论:

        因为构成三角形的充要条件是:对于三个数a < b < c,满足a + b > c。

        所以不能构成三角形的条件是:对于三个数a < b < c,满足a + b <= c。

        所以对于一个升序数列a[i],让a[i]的增加速度最小,则类似于斐波那契数列:1,1,2,3,5,8,13...

        又因为点权范围为[1,2^31-1],所以一个不能构成三角形的数列,最多有大约45个数字。

        即:对于数字个数 >= 50的数列,必定有三个数能构成三角形。

      

      所以先找出(a,b)的最近公共祖先act,然后顺着路径最多取50个数。

      然后sort一遍取出的数t[i],扫一遍有没有t[i-2]+t[i-1]>t[i]。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 #include <vector>
      6 #define MAX_N 100005
      7 #define MAX_K 20
      8 
      9 using namespace std;
     10 
     11 int n,m;
     12 int w[MAX_N];
     13 int t[MAX_N];
     14 int dep[MAX_N];
     15 int par[MAX_K][MAX_N];
     16 vector<int> edge[MAX_N];
     17 
     18 void read()
     19 {
     20     scanf("%d%d",&n,&m);
     21     for(int i=1;i<=n;i++)
     22     {
     23         scanf("%d",&w[i]);
     24     }
     25     int a,b;
     26     for(int i=0;i<n-1;i++)
     27     {
     28         scanf("%d%d",&a,&b);
     29         edge[a].push_back(b);
     30     }
     31 }
     32 
     33 void dfs(int now,int p,int d)
     34 {
     35     dep[now]=d;
     36     par[0][now]=p;
     37     for(int i=0;i<edge[now].size();i++)
     38     {
     39         int temp=edge[now][i];
     40         if(temp!=p) dfs(temp,now,d+1);
     41     }
     42 }
     43 
     44 void init_lca(int root)
     45 {
     46     dfs(root,-1,0);
     47     for(int k=0;k+1<MAX_K;k++)
     48     {
     49         for(int i=1;i<=n;i++)
     50         {
     51             if(par[k][i]==-1) par[k+1][i]=-1;
     52             else par[k+1][i]=par[k][par[k][i]];
     53         }
     54     }
     55 }
     56 
     57 int lca(int a,int b)
     58 {
     59     if(dep[a]>dep[b]) swap(a,b);
     60     for(int k=0;k<MAX_N && dep[a]!=dep[b];k++)
     61     {
     62         if(((dep[b]-dep[a])>>k)&1)
     63         {
     64             b=par[k][b];
     65         }
     66     }
     67     if(a==b) return a;
     68     for(int k=MAX_K-1;k>=0;k--)
     69     {
     70         if(par[k][a]!=par[k][b])
     71         {
     72             a=par[k][a];
     73             b=par[k][b];
     74         }
     75     }
     76     return par[0][a];
     77 }
     78 
     79 bool check(int a,int b,int act)
     80 {
     81     int cnt=0;
     82     t[cnt++]=w[act];
     83     int now=a;
     84     while(now!=act)
     85     {
     86         t[cnt++]=w[now];
     87         now=par[0][now];
     88         if(cnt>50) break;
     89     }
     90     now=b;
     91     while(now!=act)
     92     {
     93         t[cnt++]=w[now];
     94         now=par[0][now];
     95         if(cnt>50) break;
     96     }
     97     sort(t,t+cnt);
     98     for(int i=2;i<cnt;i++)
     99     {
    100         if((long long)t[i-2]+t[i-1]>t[i]) return true;
    101     }
    102     return false;
    103 }
    104 
    105 void work()
    106 {
    107     init_lca(1);
    108     int p,a,b;
    109     for(int i=0;i<m;i++)
    110     {
    111         scanf("%d%d%d",&p,&a,&b);
    112         if(p==0)
    113         {
    114             int act=lca(a,b);
    115             if(check(a,b,act)) printf("Y
    ");
    116             else printf("N
    ");
    117         }
    118         else w[a]=b;
    119     }
    120 }
    121 
    122 int main()
    123 {
    124     read();
    125     work();
    126 }
  • 相关阅读:
    bzoj-2748 2748: [HAOI2012]音量调节(dp)
    bzoj-2338 2338: [HNOI2011]数矩形(计算几何)
    bzoj-3444 3444: 最后的晚餐(组合数学)
    codeforces 709E E. Centroids(树形dp)
    codeforces 709D D. Recover the String(构造)
    codeforces 709C C. Letters Cyclic Shift(贪心)
    codeforces 709B B. Checkpoints(水题)
    codeforces 709A A. Juicer(水题)
    Repeat Number
    hdu 1003 Max Sum (动态规划)
  • 原文地址:https://www.cnblogs.com/Leohh/p/7647701.html
Copyright © 2011-2022 走看看