CF 593D LCA,贪心
2015-11-06 15:56
302 查看
题目链接: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又在找父亲这细节写错。。。真是残念啊。。。。
题意:给你一个含有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; } } } }
相关文章推荐
- SQL Linq lamda区别
- UIWebView(高级)
- apn查询网站
- 初认Objective-c NSNumber NSInteger int NSNumber转换
- Bulls and Cows
- Swift(十二、方法&下标脚本)
- hibernate的Configuration类和SessionFactory接口
- facebook海量图片存储系统与淘宝TFS系统比较
- logback.xml
- 织梦怎么动态浏览文章页面
- Android------- The connection to adb is down, and a severe error has occured.
- 限制文本框中只能输入数字
- javaWEB中前后台中文乱码问题解决方法
- SSL延迟计算:为什么HTTPs比HTTP要慢?
- 防止人为误操作MySQL数据库技巧
- maven(4)将项目发布到私服
- 关于maven的几个常用插件
- 在Web Application中集成CAS登录模块
- LintCode-链表划分
- 数据说:互联网行业哪个职位比较有前途?