CF 593D LCA,贪心

来源:互联网 发布:淘宝运营个人简历模板 编辑:程序博客网 时间:2024/05/16 10:21

题目链接:http://codeforces.com/problemset/problem/593/D


题意:给你一个含有n个点的树(2<=n<=200000),每个边有权值xi(1<=xi<=10^18),有m个询问(1<=m<=200000),每个询问别分是:1.给你一个c,从a点走到b点,每经过一个边c = c / xi,c为整数,向下取整,输出最后c的值。2.改变某条边的值,改变的值一定要比原来小,且大于等于1。


思路:对于询问a,b,找出其公共祖先,然后从任意一点出发向祖先走,走的过程中更新c值。因为边值要等于1,要么大于1。对于所有大于1的边,显然这种边最多走64次可以结束。对于等于1的边,向上递归到边值不为1的点,并把原来点的父亲直接标记到这个点,下次往上递归时直接到这个点,那么以后的向上递归次数也不会很多。复杂度为O(nlogc)。。。。。ps:比赛时没发现自己lca的错误,一直在调。。。后来过了pretest又在找父亲这细节写错。。。真是残念啊。。。。



#include<bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))using namespace std;typedef long long ll;const int maxn = 200005;int n,m;struct ppp{int v,nex;ll c;}e[maxn * 4];ll c;int head[maxn];int dp[maxn * 2][19],tole;int dep[maxn],pos[maxn],last[maxn * 2],pre[maxn];int qian[maxn];int cnt;void make_edge(int u,int v,ll c){e[tole].c = c;e[tole].v = v,e[tole].nex = head[u];head[u] = tole++;}void dfs(int u,int fa,int deep){dep[u] = deep;pos[u] = ++cnt;last[cnt] = u;pre[u] = fa;int v;for(int i = head[u];~i;i = e[i].nex){v = e[i].v;if(v == fa)continue;qian[v] = i;dfs(v,u,deep + 1);pos[u] = ++cnt;last[cnt] = u;}}void ST(){for(int i = 1;i <= cnt;i++)dp[i][0] = last[i];for(int j = 1;(1 << j) <= cnt;j++)for(int i = 1;i + (1 << j) - 1 <= cnt;i++){dp[i][j] = dp[i][j - 1];if(dep[dp[i + (1 << (j - 1))][j - 1]] < dep[dp[i][j - 1]])dp[i][j] = dp[i + (1 << (j - 1))][j - 1];}}int query(int l,int r){int k = 0;while((1 << (k + 1)) <= r - l + 1)k++;if(dep[dp[l][k]] < dep[dp[r - (1 << k) + 1][k]])return dp[l][k];else return dp[r - (1 << k) + 1][k];}void init(){mem(head,-1);tole = 0;cnt = 0;}int find(int x){if(x == 1)return 1;if(e[qian[x]].c == 1){return pre[x] = find(pre[x]);}else return x;} int x;void go(int u){if(u == 1 || u == x || dep[u] <= dep[x])return;c = c / e[qian[u]].c;int v;if(e[qian[u]].c == 1)v = find(u);else v = pre[u];if(c == 0 || dep[v] <= dep[x] || v == x)return;go(v);}int main(){while(cin>>n>>m){init();for(int i = 1,a,b;i <= n - 1;i++){scanf("%d%d%I64d",&a,&b,&c);make_edge(a,b,c);make_edge(b,a,c);}dfs(1,0,0);ST();qian[1] = 0;while(m--){int op;int a,b;scanf("%d",&op);if(op == 1){scanf("%d%d",&a,&b);cin>>c;int aa = a,bb = b;if(a == b){cout<<c<<"\n";continue;}a = pos[a],b = pos[b];if(a >= b)swap(a,b);x = query(a,b);go(aa);go(bb);cout<<c<<"\n";}else{scanf("%d%I64d",&a,&c);e[(a - 1) * 2].c = c;e[(a  - 1) * 2 + 1].c = c;}}}}


0 0
原创粉丝点击