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;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

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条边的权值改为...

codeforces 593D Happy Tree Party Lca+并查集

codeforces 593D Happy Tree Party Lca+并查集

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

D. Happy Tree Party time limit per test 3 seconds memory limit per test 256 megabytes ...

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

#include #include #include #include #include #include #include #include #include #include #include #...

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

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

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

time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandar...

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

题意:给你一棵树,每条边上有权值。有两个操作 1. u v p 从u~v的路径上用p除每跳边的权值,向下取整 2. u p 将第u条边的权值改为p 思路:树链剖分 呃…算是模板题吧 因为这道...

codeforces 593D happy tree party 树链剖分

/* 题目描述:给定一棵树及其边权,有两种操作 1 u v y 用y依次去除uv的公共路径上的每一条边的边权,注意这里的除法是整数的除法 2 x p 把第x条输入边的边权变为p ...

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

题意: 给定一颗N≤2×105的边权树,Q≤2×105给定一颗N\le 2\times 10^5的边权树, Q\le 2\times 10^5 1. a b y,从a到b的路径,y不断对对所...
  • lwt36
  • lwt36
  • 2016-01-24 23:16
  • 220

【并查集】【模拟】Codeforces 698B & 699D Fix a Tree

题目链接:   http://codeforces.com/problemset/problem/699/D 题目大意:   通过给定当前节点的父亲给你一棵有错的树,可能有多个根和环,输出改成...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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