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

    题目链接:BZOJ 3251

    Description

    给定一大小为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

     分析

    只要在一条路径上找到三个数,使他们成为三角形就好

    因为找不到三个数成三角形的条件太苛刻了

    对任意三个数a1,a2,a3必须满足a1+a2<=a3

    按从小到大排列这些数,发现他们的增长是很快的

    最接近三角形的就是大小相邻的三个数

    取等时不就是斐波那契嘛

    那在47项的时候就爆int了

    哦,47个数以上的,就必定会有三个数成三角形

    over

    有的时候正向不好想可以反向来

    注意条件苛刻的地方,往往就是突破口

    代码

      1 /*****************************
      2 User:Mandy.H.Y
      3 Language:c++
      4 Problem:Triangle
      5 *****************************/
      6 //一剑霜寒十四州 
      7 #include<bits/stdc++.h>
      8 #define Max(x,y) ((x) > (y) ? (x) : (y))
      9 #define Min(x,y) ((x) < (y) ? (x) : (y))
     10 
     11 using namespace std;
     12 
     13 const int maxn = 1e5 + 5;
     14 
     15 int n,q,size;
     16 long long val[maxn];
     17 int father[maxn],dep[maxn];
     18 int first[maxn],cnt[maxn];
     19 int top[maxn];
     20 long long cur[maxn];
     21 
     22 struct Edge{
     23     int v,nt;
     24 }edge[maxn << 1];
     25 
     26 template<class T>inline void read(T &x){
     27     x = 0;bool flag = 0;char ch = getchar();
     28     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
     29     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
     30     if(flag) x = -x;
     31 }
     32 
     33 template<class T>void putch(const T x){
     34     if(x > 9) putch(x / 10);
     35     putchar(x % 10 | 48);
     36 }
     37 
     38 template<class T>void put(const T x){
     39     if(x < 0) putchar('-'),putch(-x);
     40     else putch(x);
     41 }
     42 
     43 void file(){
     44     freopen("Triangle.in","r",stdin);
     45     freopen("Triangle.out","w",stdout);
     46 }
     47 
     48 void eadd(int u,int v){
     49     edge[++size].v = v;
     50     edge[size].nt = first[u];
     51     first[u] = size;
     52 }
     53 
     54 void readdata(){
     55     read(n);read(q);
     56     for(int i = 1;i <= n; ++ i) read(val[i]);
     57     for(int i = 1;i < n; ++ i){
     58         int u,v;
     59         read(u);read(v);
     60         eadd(u,v);
     61         father[v] = u;
     62     }
     63 }
     64 
     65 void dfs(int u){
     66     top[u] = u;
     67     int son = 0,mcnt = 0;
     68     cnt[u] = 1;
     69     for(int i = first[u];i;i = edge[i].nt){
     70         int v = edge[i].v;
     71         dep[v]=dep[u]+1;
     72         dfs(v);
     73         cnt[u] += cnt[v];
     74         if(cnt[v] > mcnt){
     75             mcnt = cnt[v];
     76             son = v;
     77         }
     78     }
     79     if(son) top[son] = u;
     80 }
     81 
     82 int find(int x){
     83     return top[x] == x ? x : top[x] = find(top[x]);
     84 }
     85 
     86 int LCA(int x,int y){
     87     if(find(x) == find(y)) return dep[x] < dep[y] ? x : y;
     88     else return dep[top[x]] < dep[top[y]] ? LCA(x,father[top[y]]) : LCA(y,father[top[x]]);
     89 }
     90 
     91 void work(){
     92     dep[1] = 1;
     93     dfs(1);
     94     while(q--){
     95         int t;
     96         read(t);
     97         if(t == 0) {
     98             int a,b;
     99             read(a);read(b);
    100             int anc = LCA(a,b);
    101             int num = dep[a]+dep[b]-(dep[anc]<<1)+1;
    102             if(num > 50) puts("Y");
    103 //一个三角形都没有的条件是很苛刻的
    104 //任意三个数中,较小的两个数的和必须小于等于最大的数
    105 //这种数列最长应该是斐波那契
    106 //而斐波那契在47项就爆int了 
    107             else{
    108                 int tot = 0,fa = a;
    109                 while(fa != anc){
    110                     cur[++tot] = val[fa];
    111                     fa = father[fa];
    112                 }
    113                 fa = b;
    114                 while(fa != anc){
    115                     cur[++tot] = val[fa];
    116                     fa = father[fa];
    117                 }
    118                 bool judge = 0;
    119                 cur[++tot] = val[anc];
    120                 sort(cur + 1,cur + 1 + tot);
    121                 for(int i = 3;i <= tot; ++ i){
    122                     if(cur[i] < cur[i-1]+cur[i-2]) {
    123                         puts("Y");
    124                         judge = 1;
    125                         break;
    126                     }
    127                 }
    128                 if(!judge) puts("N");
    129             } 
    130         } else {
    131             long long a,b;
    132             read(a);read(b);
    133             val[a] = b;
    134         }
    135     }
    136 }
    137 
    138 int main(){
    139 //    file();
    140     readdata();
    141     work();
    142     return 0;
    143 }
    View Code
  • 相关阅读:
    Roads in the North
    Labyrinth
    英语写作(二)
    语法长难句笔记
    英语写作(一)
    MySQL笔记(二)
    MySQL笔记(一)
    Mybatis简单使用与配置
    Mybatis映射文件
    什么是serializable接口?
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11505433.html
Copyright © 2011-2022 走看看