Codeforces Round #329 (Div. 2)D LCA+并查集路径压缩
来源:互联网 发布:淘宝网长袖两片连衣裙 编辑:程序博客网 时间:2024/05/21 14:01
链接:http://codeforces.com/problemset/problem/593/D
题意:一棵树,有边权,
两种操作:其一,改变边权(边权只能越改越小并且大于1)。其二,给一个X(1----1e18),和a,b两点,问X / (简单路径的边权乘积)
思路:1.裸树链剖分,维护区间乘积就可以。。爆LL的区间直接记做一个inf。。但是不太会树链剖分,考虑一个退而求其次的方法。
2.直接跑找LCA,用到边权越来越小,所以对于边权为1的点用并查集路径压缩一下,这样就可以确保log次使得X为0或者求出来值了。
PS。。开始还傻傻的用ST求了LCA。。其实根据上面的性质暴力求LCA就可以了。
代码:(预处理LCA的。。虽说是多此一举。。)
#include <bits/stdc++.h>using namespace std;const int MAXN = 200010;int rmq[2*MAXN],tot,head[MAXN],F[MAXN*2],P[MAXN],cnt,fat[MAXN],pa[MAXN],E[MAXN][2];long long v[MAXN];int findset(int a) {if(pa[a] != a) return pa[a] = findset(pa[a]);return pa[a];}void un(int a, int b){int a1 = findset(a),b1 = findset(b);if(a1 != b1) pa[a1] = b1;}struct ST{ int mm[2*MAXN],dp[2*MAXN][20]; void init(int n){ mm[0] = -1; for(int i = 1; i <= n; i++){ mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1]; dp[i][0] = i; } for(int j = 1; j <= mm[n]; j++) for(int i = 1; i + (1<<j) - 1 <= n; i++) dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1]; } int query(int a,int b){ if(a > b)swap(a,b); int k = mm[b-a+1]; return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k]; }}st;struct Edge{ int to,next; long long val;}edge[MAXN*2];void init(){ tot = 0; memset(head,-1,sizeof(head)); for(int i = 0; i < MAXN; i++) pa[i] = i; memset(fat,-1,sizeof(fat)); memset(v,-1,sizeof(v));}void addedge(int u,int v,long long c){ edge[tot].to = v; edge[tot].val = c; edge[tot].next = head[u]; head[u] = tot++;}void dfs(int u,int pre,int dep,long long val){ F[++cnt] = u; rmq[cnt] = dep; P[u] = cnt; fat[u]=pre; v[u]=val; if(u!=pre&&val==1) un(u,pre); for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if(v == pre)continue; dfs(v,u,dep+1,edge[i].val); F[++cnt] = u; rmq[cnt] = dep; }}void LCA_init(int root,int node_num){ cnt = 0; dfs(root,root,0,-1); st.init(2*node_num-1);}int query_lca(int u,int v){ return F[st.query(P[u],P[v])];}int main(){ int n,m,a,b,ttt=0,tp; long long c; scanf("%d%d",&n,&m); init(); for(int i=0;i<n-1;i++){ scanf("%d%d%I64d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); E[++ttt][0]=a; E[ttt][1]=b; } LCA_init(1,n); for(int i=0;i<m;i++){ scanf("%d",&tp); if(tp==1){ scanf("%d%d%I64d",&a,&b,&c); a=findset(a);b=findset(b); int x=findset(query_lca(a,b)); for(;c!=0&&a!=x;a=findset(fat[a])) c/=v[a]; for(;c!=0&&b!=x;b=findset(fat[b])) c/=v[b]; printf("%I64d\n",c); } else{ scanf("%d%I64d",&b,&c); if(fat[E[b][1]]==E[b][0]) swap(E[b][1],E[b][0]); v[E[b][0]]=c; if(c==1) un(E[b][0],E[b][1]); } } return 0;}
精简:
#include <bits/stdc++.h>using namespace std;const int MAXN = 200010;int tot,head[MAXN],P[MAXN],fat[MAXN],pa[MAXN],E[MAXN][2];long long v[MAXN];int findset(int a) {if(pa[a] != a) return pa[a] = findset(pa[a]);return pa[a];}void un(int a, int b){int a1 = findset(a),b1 = findset(b);if(a1 != b1) pa[a1] = b1;}struct Edge{ int to,next; long long val;}edge[MAXN*2];void init(){ tot = 0; memset(head,-1,sizeof(head)); for(int i = 0; i < MAXN; i++) pa[i] = i; memset(fat,-1,sizeof(fat)); memset(v,-1,sizeof(v));}void addedge(int u,int v,long long c){ edge[tot].to = v; edge[tot].val = c; edge[tot].next = head[u]; head[u] = tot++;}void dfs(int u,int pre,int dep,long long val){ P[u] = dep; fat[u]=pre; v[u]=val; if(u!=pre&&val==1) un(u,pre); for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if(v == pre)continue; dfs(v,u,dep+1,edge[i].val); }}int main(){ int n,m,a,b,ttt=0,tp; long long c; scanf("%d%d",&n,&m); init(); for(int i=0;i<n-1;i++){ scanf("%d%d%I64d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); E[++ttt][0]=a; E[ttt][1]=b; } dfs(1,1,0,-1); for(int i=0;i<m;i++){ scanf("%d",&tp); if(tp==1){ scanf("%d%d%I64d",&a,&b,&c); a=findset(a);b=findset(b); while(a!=b&&c!=0){ if(P[a]<P[b]) swap(a,b); c/=v[a]; a=findset(fat[a]); } printf("%I64d\n",c); } else{ scanf("%d%I64d",&b,&c); if(fat[E[b][1]]==E[b][0]) swap(E[b][1],E[b][0]); v[E[b][0]]=c; if(c==1) un(E[b][0],E[b][1]); } } return 0;}
0 0
- Codeforces Round #329 (Div. 2)D LCA+并查集路径压缩
- 【Codeforces Round 329 (Div 2) D】【LCA+并查集路径压缩】Happy Tree Party 除上两点间路径全部权值
- Codeforces Round #218 (Div. 2)---D. Vessels(并查集)
- Codeforces Round #400 (Div. 1 + Div. 2, combined) D. The Door Problem 开关--并查集
- CF Round#396D (Div. 2)(Codeforces 766D) 简单并查集+map
- codeforces 593D(并查集 + LCA)
- Codeforces Round #250 (Div. 2)(B,C,D并查集)
- Codeforces Round #268 (Div. 2) D Two Sets[并查集]
- Codeforces Round #250 (Div. 2) (D. The Child and Zoo(并查集))
- Codeforces Round #363 (Div. 2) D. Fix a Tree (并查集)
- Codeforces Round #363 (Div. 2)D. Fix a Tree(并查集)
- Codeforces Round #363 (Div. 2) Problem D - Fix a Tree(并查集 + 构造)
- Codeforces Round #363 (Div. 2) D. Fix a Tree(并查集)
- Codeforces Round #363 (Div. 2)D. Fix a Tree并查集
- Codeforces Round #363 (Div. 2) D. Fix a Tree(并查集)(判断圆环)
- Codeforces Round #396 (Div. 2)-D. Mahmoud and a Dictionary(关系并查集)
- Codeforces Round #396 (Div. 2)-D. Mahmoud and a Dictionary(并查集)
- Codeforces Round #396 (Div. 2) D. Mahmoud and a Dictionary(并查集)
- android studio 打arr包
- 个人对Redis的一些简单理解
- "Could not find Developer Disk Image"内附Xcode8.2之前版本配置iOS10、iOS 10.1、iOS10.2 配置包
- AE的PartialRefresh
- Apk反编译&回编译(二)
- Codeforces Round #329 (Div. 2)D LCA+并查集路径压缩
- MFC 生成LOG文件的示例代码
- 如何使用nodejs去访问我们的mongodb数据库
- Swift的Podfile文件创建与使用规范
- 动态内存分配
- 前端问题(1)
- 树莓派服务器搭建过程
- 分布式版本控制系统常用命令汇总
- 图像自动去暗角算法