LCA + 并查集 Happy Tree Party codeforces593D

来源:互联网 发布:一搜网络一搜同志0731 编辑:程序博客网 时间:2024/06/06 06:33

一个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         :CrystalCreated 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 500005int 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 LOCALfreopen("in.txt", "r", stdin);//freopen("out.txt","w",stdout);#endifcin >> 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;}


0 0