LCA + 并查集 Happy Tree Party codeforces593D

原创 2015年11月17日 17:22:35

一个64位的数,最多在被大于1的数整除64次后就变为0

所以对于每次访问,我们最多除64次

那么我们就要将为1的路压缩,使用并查集

每次访问使用lca,找到公共祖先lc,然后u->lc,v->lc,访问这两条路

记得并查集的时候要用

return par[u] == u ? u : par[u] = find(par[u]);

不要用

return par[u] == u ? u :  find(par[u]);

后者也能查询,但是前者再并在一起省时,不然会t的

/********************************************
Author         :Crystal
Created Time   :
File Name      :
********************************************/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
//#define LOCAL
#define maxn 500005
int root = 1;
int head[maxn],nxt[maxn],pnt[maxn];
int par[maxn];
ll cost[maxn];
int dep[maxn],far[maxn],p[maxn][30];
ll path[maxn][30];
int dis[maxn];
int u[maxn];
int v[maxn];
ll c[maxn];
int cnt = 0;
int n,q;
int find(int u){
	return par[u] == u ? u : par[u] = find(par[u]);
}
void addedge(int u,int v,ll c){
	pnt[cnt] = v;
	nxt[cnt] = head[u];
	cost[cnt] = c;
	head[u] = cnt++;
}
int llog = 20;
void dfs(int u,int f,int d){
	dep[u] = d;
	p[u][0] = f;
	for(int i=head[u];~i;i = nxt[i]){
		int v = pnt[i];
		if(v == f)continue;
		path[v][0] = cost[i];
		dfs(v, u, d+1); 
	}
}
void init(){
	dfs(root, -1, 0);
	for(int i=0;i+1<llog;i++){
		for(int v=1;v<=n;v++){
			if(p[v][i] == -1)p[v][i+1] = -1;
			else p[v][i+1] = p[p[v][i]][i];
		}
	}
}
int lca(int u,int v){
	if(dep[u] > dep[v])swap(u,v);
	for(int i=0;i<llog;i++){
		if(dep[v]-dep[u] >> i & 1){
			v = p[v][i];
		}
	}
	if(u == v)return u;
	for(int i=llog - 1;i != -1;i--){
		if(p[u][i] != p[v][i]){
			u = p[u][i];
			v = p[v][i];
		}
	}
	return p[u][0];
}
ll solve(int u,int v,ll x){
	//cout << u <<v <<x << endl;
	int cnt = 0;
	while(x && dep[u] < dep[v] && cnt < 65){
		v = find(v);
		if(dep[u] >= dep[v])break;
		x /= path[v][0];
		v = p[v][0];
		cnt++;
	}
	return x;
}
int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
	cin >> n >> q;
	MEM(head,-1);
	for(int i=1;i<n;i++){
		scanf("%d%d%lld",&u[i],&v[i],&c[i]);
		addedge(u[i],v[i],c[i]);
		addedge(v[i],u[i],c[i]);
	}
	for(int i=1;i<=n;i++)par[i] = i;
	init();
	for(int i=1;i<n;i++){
		if(c[i]==1){
			if(dep[u[i]] > dep[v[i]]){
				par[u[i]] = find(v[i]);
			}
			else{
				par[v[i]] = find(u[i]);
			}
		}
	}
	for(int i=1;i<=q;i++){
		int f;cin >> f;
		if(f==1){
			int u,v;
			ll x;
			scanf("%d%d%lld",&u,&v,&x);
			int lc = lca(u,v);
			//cout << lc  << endl;
			x = solve(lc,u,x);
			x = solve(lc,v,x);
			printf("%lld\n",x);
		}
		else{
			int load;
			ll x;scanf("%d%lld",&load,&x);
			int a = u[load];
			int b = v[load];
			if(dep[a]>dep[b]){
				path[a][0] = x;
			}
			else{
				path[b][0] = x;
			}
			if(x == 1){
				if(dep[a]>dep[b]){
					par[a] = find(b);
				}
				else par[b] = find(a);
			}
		}
	}
	return 0;
}





【并查集专题】【HDU】

How Many Tables Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...
  • zy691357966
  • zy691357966
  • 2014年11月29日 18:34
  • 1935

【BZOJ3910】火车 LCA+并查集

题解: 首先找两点之间路径可以用倍增LCA。 然后标记哪个点走过可以用并查集,均摊下来最后是线性的。 代码: #include #include #include #include ...
  • Vmurder
  • Vmurder
  • 2015年03月31日 16:08
  • 1056

二叉搜索树(BST)的最近公共祖先(LCA)问题(Lowest Common Ancestor of a Binary Tree)

给定二叉搜索树中的任意两点,找出它们的最近公共祖先。 1、最近公共祖先(LCA)                           在上图这棵树中,绿色节点表示x和y的公共祖先,深绿色节点表示x...
  • yike1207
  • yike1207
  • 2015年03月23日 16:59
  • 1093

CodeForces 593D Happy Tree Party(树链剖分(边权) or LCA+并查集)

题意:给你一棵数,n个点n-1条边,每条边有个权值,q次询问,询问有两种: 1 a b y : a到b的路径上不断进行y = y/xi(像下取整),问最后y的值 2 p c :  将第p条边的权值改为...
  • CillyB
  • CillyB
  • 2017年08月09日 01:32
  • 225

codeforces 593D Happy Tree Party Lca+并查集

codeforces 593D Happy Tree Party Lca+并查集
  • wzq_QwQ
  • wzq_QwQ
  • 2015年11月06日 07:38
  • 762

codeforces 593 D. Happy Tree Party (LCA + 并查集)

D. Happy Tree Party time limit per test 3 seconds memory limit per test 256 megabytes ...
  • whai362
  • whai362
  • 2015年11月05日 20:30
  • 511

【Codeforces Round 329 (Div 2) D】【LCA+并查集路径压缩】Happy Tree Party 除上两点间路径全部权值

#include #include #include #include #include #include #include #include #include #include #include #...
  • snowy_smile
  • snowy_smile
  • 2015年11月06日 20:42
  • 404

[CodeForces 593D]Happy Tree Party[LCA][路径压缩]

题目链接:[CodeForces 593D]Happy Tree Party[LCA][路径压缩] 题意分析: 给出两个操作,1和2。 1代表查询结点a到结点b之间最短路径,将路径上的权值对y进行向下...
  • CatGlory
  • CatGlory
  • 2015年11月21日 10:44
  • 542

【13.91%】【codeforces 593D】Happy Tree Party

time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandar...
  • harlow_cheng
  • harlow_cheng
  • 2016年11月11日 09:55
  • 119

Codeforces Round #329 (Div. 2) 593D. Happy Tree Party(树链剖分)

题意:给你一棵树,每条边上有权值。有两个操作 1. u v p 从u~v的路径上用p除每跳边的权值,向下取整 2. u p 将第u条边的权值改为p 思路:树链剖分 呃…算是模板题吧 因为这道...
  • qq_27925701
  • qq_27925701
  • 2016年01月27日 13:58
  • 242
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:LCA + 并查集 Happy Tree Party codeforces593D
举报原因:
原因补充:

(最多只允许输入30个字)