zoukankan      html  css  js  c++  java
  • [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
    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


    这题直接暴力!!!

    考虑一下不能凑出三角形的木棍长度排列

    1,2,3,5,8,11,...

    就是Fibonacci数列,所以路径长度>50就直接输出Y,否则暴力判断。。。

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1;char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)    putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e5;
    vector<ui>vec;
    int v[N+10];
    struct S1{
    	int pre[(N<<1)+10],now[N+10],child[(N<<1)+10],tot;
    	int deep[N+10],fa[N+10],Rem[N+10],top[N+10],size[N+10];
    	void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
    	void insert(int x,int y){join(x,y),join(y,x);}
    	void dfs(int x){
    		deep[x]=deep[fa[x]]+1,size[x]=1;
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa[x])	continue;
    			fa[son]=x,dfs(son);
    			size[x]+=size[son];
    			if (size[Rem[x]]<size[son])	Rem[x]=son;
    		}
    	}
    	void build(int x){
    		if (!x)	return;
    		top[x]=Rem[fa[x]]==x?top[fa[x]]:x;
    		build(Rem[x]);
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa[x]||son==Rem[x])	continue;
    			build(son);
    		}
    	}
    	int Lca(int x,int y){
    		while (top[x]!=top[y]){
    			if (deep[top[x]]<deep[top[y]])	swap(x,y);
    			x=fa[top[x]];
    		}
    		return deep[x]<deep[y]?x:y;
    	}
    	bool work(int x,int y){
    		int lca=Lca(x,y);
    		if (deep[x]+deep[y]-2*deep[lca]+1>50)	return 1;
    		vec.clear(); vec.push_back(v[lca]);
    		for (;x!=lca;x=fa[x])	vec.push_back(v[x]);
    		for (;y!=lca;y=fa[y])	vec.push_back(v[y]);
    		sort(vec.begin(),vec.end());
    		for (vector<ui>::iterator i=vec.begin();i!=vec.end();i++)
    			for (vector<ui>::iterator j=i+1;j!=vec.end();j++)
    				for (vector<ui>::iterator k=j+1;k!=vec.end();k++)
    					if (*k<*j+*i)	return 1;
    		return 0;		
    	}
    }HLD;//Heavy Light Decomposition
    int main(){
    	int n=read(),m=read();
    	for (int i=1;i<=n;i++)	v[i]=read();
    	for (int i=1;i<n;i++){
    		int x=read(),y=read();
    		HLD.insert(x,y);
    	}
    	HLD.dfs(1),HLD.build(1);
    	for (int i=1;i<=m;i++){
    		int type=read(),x=read(),y=read();
    		if (type==0)	printf(HLD.work(x,y)?"Y
    ":"N
    ");
    		if (type==1)	v[x]=y;
    	}
    	return 0;
    }
    
  • 相关阅读:
    HDU 1525 Euclid's Game 博弈
    HDU 1272 小希的迷宫 并查集
    HDU1232 畅通工程 并查集
    HDU1760 A New Tetris Game NP态
    HDU5795A Simple Nim SG定理
    UVA10561 Treblecross 组合游戏/SG定理
    HDU1848 Fibonacci again and again SG函数
    HDU1532 Drainage Ditches 网络流EK算法
    树状数组小结
    HDU3333 Turing Tree 树状数组+离线处理
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/9994289.html
Copyright © 2011-2022 走看看