bzoj3251: 树上三角形(思维题)

  神tmWA了8发调了20min才发现输出没回车T T...

  首先考虑一段什么样的序列才会是N... 显然最长的形式就是斐波那契,前两数之和等于第三数之和,这样就无法组成三角形并且序列最长。可以发现在int范围内斐波那契数列不会超过50个,所以如果这段路径上节点数超过50个直接输出Y,否则把50个数拉出来排序暴力找是否有三角形就好了。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010;
struct poi{int too, pre;}e[maxn<<1];
int n, q, ty, x, y, cnt, tot;
int a[maxn], d[maxn], fa[maxn], last[maxn], st[maxn];
void read(int &k)
{
    int f=1; k=0; char c=getchar();
    while(c<‘0‘ || c>‘9‘) c==‘-‘ && (f=-1), c=getchar();
    while(c<=‘9‘ && c>=‘0‘) k=k*10+c-‘0‘, c=getchar();
    k*=f;
}
inline void add(int x, int y){e[++tot]=(poi){y, last[x]}; last[x]=tot;}
void dfs(int x)
{
    d[x]=d[fa[x]]+1;
    for(int i=last[x], too;i;i=e[i].pre)
    fa[too=e[i].too]=x, dfs(too);
}
inline bool query(int x, int y)
{
    int cnt=0;
    while(cnt<50)
    {
        if(d[x]<d[y]) swap(x, y);
        st[++cnt]=a[x];
        if(x==y) break; x=fa[x];
    }
    if(cnt>=50) return 1;
    sort(st+1, st+1+cnt);
    for(int i=1;i<=cnt-2;i++)
    if((ll)st[i]+st[i+1]>st[i+2]) return 1;
    return 0;
}
int main()
{
    read(n); read(q);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<n;i++) read(x), read(y), add(x, y);
    dfs(1);
    for(int i=1;i<=q;i++)
    {
        read(ty); read(x); read(y);
        if(!ty) printf("%s\n", query(x, y)?"Y":"N");
        else a[x]=y;
    }
}

时间: 2024-10-05 03:42:34

bzoj3251: 树上三角形(思维题)的相关文章

BZOJ3251 树上三角形

一看这题...难道要链剖乱搞什么的吗...不会啊汗... 突然发现不构成三角形的条件其实非常苛刻,由斐波那契数列: 1,1,2,3,5,8,13,21,34...... 可以知道其实小于int的大概就50项的样子. 于是路径长度>50直接输出'Y',否则排序判断... 看来还是蛮快的... 1 /************************************************************** 2 Problem: 3251 3 User: rausen 4 Langu

【BZOJ3251】树上三角形 暴力

[BZOJ3251]树上三角形 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 Output 对每个询问输出一行表示答案,

ACM: Gym 101047K Training with Phuket&#39;s larvae - 思维题

Gym 101047K Training with Phuket's larvae Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Practice Description standard input/output Thai cuisine is known for combining seasonings so that every dish has flavors that are s

hdu5325 树的思维题

http://acm.hdu.edu.cn/showproblem.php?pid=5325 Problem Description Bobo has a tree,whose vertices are conveniently labeled by 1,2,...,n.Each node has a weight wi. All the weights are distrinct. A set with m nodes v1,v2,...,vm is a Bobo Set if: - The

Unique Encryption Keys (思维题 预处理)

题目 题意:给m个数字, q次询问, 询问b到e之间如果有重复数字就输出, 没有就输出OK 思路:用f[i]数组 记录从i开始向后最近的有重复数字的 位置, 如 1 3 2 2, 则f[1] = 4; 如果离a最近的重复数字的位置 都大于b, 就说明没有重复数字. f[]数组需要预处理,从后向前. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector>

sdut 2847 Monitor (思维题)

题目 题意:给定a, b, x, y;  求使c, d; 使c:d = x :y; 且c<=a, d<=b, 而且c, d尽量大. 先求最小倍数, 再用最小倍数乘 x, y; 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 7 long long gcd(long long a, l

hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10

题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include &

学习方法_2011年编写和锻炼的思维题

1.多看,多练,多想,多总结,最重要就是不停的写代码! 给自己的目标:一天代码量最少800行,无论是什么代码,如果练习的量不够,就重复做已经写过的代码. 思维题: 找出这当中数字 1,11,31,4113,612314 的规律是怎样的? 1,11,表示前面的数有1个131,表示前面所有的数有3个14113,表示前面的所有的数有4个1.1个3以此类推,前面所有的数有6个1.2个3.1个4,即为612314 1.两个无窗的房间,其中一间有三个电灯,另一间里面有三个开关,三个开关各控制三个电灯.问:每

HDU 2091 空心三角形 --- 水题

/* HDU 2091 空心三角形 --- 水题 */ #include <cstdio> int main() { int kase = 0; char ch; int h, t; //h表示高 while (scanf("%c", &ch) == 1 && ch != '@'){ scanf("%d", &h); if (kase++){ printf("\n"); } getchar(); if