BZOJ 3251: 樹上三角形

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」表示無解。ios

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
git

思路:

  腦洞題,考慮到MAXINT範圍內徹底不能構成三角形的數字有多少---Fib數列,在47項的時候爆INT,因此只要路徑上有超過47個點直接輸出Y,沒有超過47個點能夠暴力把全部點壓入數組,並排序枚舉相鄰三個點可否構成三角形,注意存在兩點相加爆INT的狀況,枚舉以後不知足則輸出N,由於每次暴力不超過50,因此複雜度至關低。我考場上還寫了一個樹剖,汗。相似找LCA的過程,一層一層爬就好,記得在循環裏判當前是否到47個了!數組

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <iostream>
using namespace std;
const int N = 120000;
int fa[N],dep[N],pv[N];
int q[60];
inline char nc() {
	static char buf[100000], *p1, *p2;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin)),p1==p2?EOF:*p1++;
}
inline int read() {
	int x=0;char ch=nc();
	while(!isdigit(ch))ch=nc();
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=nc();}
	return x;
}
int cnt,head[N<<2],to[N<<2],next[N<<2];
inline void add_edge(int a,int b) {
	to[++cnt]=b;
	next[cnt]=head[a];
	head[a]=cnt;
	to[++cnt]=a;
	next[cnt]=head[b];
	head[b]=cnt;
}
void dfs1(int p) {
	dep[p]=dep[fa[p]]+1;
	int i;
	for(i=head[p];i;i=next[i]) {
		if(to[i]!=fa[p]) {
			fa[to[i]]=p;
			dfs1(to[i]);
		}
	}
}
void query(int a,int b) {
	int cnt1=0;
	if(dep[b]>dep[a])
		swap(a,b);
	while(dep[a]>dep[b]) {
		q[++cnt1]=pv[a];
		a=fa[a];
		if(cnt1>46) {
			puts("Y");
			return;
		}
	}
	while(a!=b) {
		q[++cnt1]=pv[a];
		q[++cnt1]=pv[b];
		a=fa[a],b=fa[b];
		if(cnt1>46) {
			puts("Y");
			return;
		}
	}
	q[++cnt1]=pv[a];
	if(cnt1>46) {
		puts("Y");
		return;
	}
	sort(q+1,q+cnt1+1);
	int i;
	for(i=3;i<=cnt1;i++) {
		if(q[i]-q[i-2]<q[i-1]) {
			puts("Y");
			return;
		}
	}
	puts("N");
}
int main() {
	int n,q;
	n=read(),q=read();
	int i;
	for(i=1;i<=n;i++)
		pv[i]=read();
	int x,y;
	for(i=1;i<n;i++) {
		x=read(),y=read();
		add_edge(x,y);
	}
	dfs1(1);
	//dfs2(1,1,1);
	/*for(i=1;i<=n;i++) {
		printf("%d\n",len[i]);
	}*/
	while(q--) {
		int opt=read();
		if(opt) {
			x=read(),y=read();
			pv[x]=y;
		}
		else {
			x=read(),y=read();
			query(x,y);
		}
	}
}

 歡迎到原博客看看 >原文連接<spa

相關文章
相關標籤/搜索