SP375 Query on a tree【树链剖分】

来源:互联网 发布:淘宝大学金牌讲师小飞 编辑:程序博客网 时间:2024/06/11 01:27

题意:给定一棵树,求一条路径上的边权最大值


思路:树链剖分,把一颗树,转化成一个区间,就可以用线段树,快速解决一些问题了

至此用这个模板终于会处理点权问题了,LCA那个dfs序转成链,我不会算点权的


#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<stdlib.h>#include<math.h>#include<vector>#include<list>#include<map>#include<stack>#include<queue>#include<algorithm>#include<numeric>#include<functional>using namespace std;typedef long long ll;typedef pair<int,int> pii;#define lson(x) 2*x#define rson(x) 2*x+1const int maxn = 1e4+5;struct Edge{int to,next,cost;}edge[maxn*4];int e1[maxn],e2[maxn],cost[maxn];int head[maxn],tot,cnt;int root,size[maxn],dep[maxn],fa[maxn],son[maxn];int top[maxn],id[maxn],val[maxn];/*size -> 以x为根节点子树的大小   dep -> 深度 fa   -> 父节点                  son -> 重儿子 top  -> x所在重链的顶端节点     id -> 这个点在线段树中的位置 */struct data{int l,r,num;}node[maxn*4];void init(){memset(head,-1,sizeof head);tot = 0;cnt = 0;}void add(int x,int y,int val){edge[tot].to = y;edge[tot].cost = val;edge[tot].next = head[x];head[x] = tot++;}int dfs1(int x,int pre,int d){size[x] = 1;fa[x] = pre;dep[x] = d;son[x] = 0;for(int i = head[x]; i != -1; i = edge[i].next){int y = edge[i].to;if(y != pre){size[x] += dfs1(y,x,d+1);if(size[y] > size[son[x]])son[x] = y;}}return size[x];}void dfs2(int x,int pre){id[x] = ++cnt;top[x] = pre;if(son[x]) dfs2(son[x],pre); //重链 for(int i = head[x]; i != -1; i = edge[i].next){int y = edge[i].to;if(y != fa[x] && y != son[x])dfs2(y,y); //轻链}}void pushup(int cnt){node[cnt].num = max(node[lson(cnt)].num,node[rson(cnt)].num);}void build(int x,int y, int cnt){node[cnt].l = x;node[cnt].r = y;if(x == y){node[cnt].num = val[x];return;}int mid = (x+y) / 2;build(x,mid,lson(cnt));build(mid+1,y,rson(cnt));pushup(cnt);}void up(int x,int y,int cnt,int val){if(x == node[cnt].l && y == node[cnt].r){node[cnt].num = val;return;}int fa = 2*cnt;if(x <= node[fa].r){if(y <= node[fa].r)up(x,y,fa,val);elseup(x,node[fa].r,fa,val);}fa++;if(y >= node[fa].l){if(x >= node[fa].l)up(x,y,fa,val);elseup(node[fa].l,y,fa,val);}pushup(cnt);}int fid(int x,int y,int cnt){int res = 0;if(x == node[cnt].l && y == node[cnt].r){return node[cnt].num;}int fa = 2*cnt;if(x <= node[fa].r){if(y <= node[fa].r)res = max(res,fid(x,y,fa));elseres = max(res,fid(x,node[fa].r,fa));}fa++;if(y >= node[fa].l){if(x >= node[fa].l)res = max(res,fid(x,y,fa));elseres = max(res,fid(node[fa].l,y,fa));}return res;}int qurey(int u,int v){int ans = 0;while(top[u] != top[v]){if(dep[top[u]] < dep[top[v]])swap(u,v);ans = max(ans,fid(id[top[u]],id[u],1));u = top[u];u = fa[u];}if(dep[u] > dep[v])swap(u,v);ans = max(ans,fid(id[son[u]],id[v],1)); return ans;//存的都是点的父边,最上面的点用son[u] }int main(){int T,n,kase = 1;char ch[50];scanf("%d",&T);while(T--){if(kase++ != 1)putchar('\n');scanf("%d",&n);init();for(int i = 1; i < n; i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);e1[i] = a;e2[i] = b;cost[i] = c;add(a,b,c);add(b,a,c);}root = (n+1) / 2;dfs1(root,root,1);dfs2(root,root);for(int i = 1; i < n; i++){if(dep[ e1[i] ] < dep[ e2[i] ])swap(e1[i],e2[i]);val[ id[e1[i]] ] = cost[i];}build(1,cnt,1);while(scanf("%s",ch)!=EOF && ch[0]!='D'){int a,b;scanf("%d%d",&a,&b);if(ch[0] == 'Q'){int ans = qurey(a,b);printf("%d\n",ans);}elseup(id[e1[a]],id[e1[a]],1,b);}}}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 注册微信公众号邮箱激活不了怎么办 不是自己申请的qq号忘密码怎么办 联通宽带拨号账号密码忘记了怎么办 忘了路由器的用户名和密码怎么办 宽带连接用户名和密码忘了怎么办 江西银行网银用户名忘记了怎么办 江西银行网银密码忘了怎么办 广发信用卡网银密码忘了怎么办 刚注册的淘宝账号买不了东西怎么办 隐藏后的wif不知道用户名怎么办 脊柱侧弯术后钢钉断了一根怎么办 对法院执行裁定申请复议过期怎么办 自己家店名被别人注册了商标怎么办 有人去工商局投诉我公司了怎么办 急用钱怎么办啊有没有什么贷款啊 初级会计报名信息表没打印怎么办 电工证复审流程时间过了怎么办 应版权方要求无法下载的电影怎么办 手机设置蜜码小孩都能破解该怎么办 拍到了上海车牌不想买车了怎么办 买车4s店不给临时车牌怎么办 百度云谣绑定的邮箱被绑定了怎么办 百度网盘分享的视频打不开怎么办 在赶集网登录时忘记验证码该怎么办 支付宝绑定的手机号是空号了怎么办 微信聊天后电话号码重复是怎么办 老婆在外省工作不回到我身边怎么办 知道扣扣号怎样盗取他的密码怎么办 喜欢养猫又怕猫破坏家里怎么办 约她她每次都找借口怎么办? 遇到总是找借口不还钱的人怎么办 装修好了业主找借口不给钱怎么办 荒野行动手机换了帐号登不上怎么办 换新手机后微信头像都没有了怎么办 苹果系统维护换不了微信头像怎么办 系统通知栏不显示qq图标怎么办 快递号码写错了而且发货了怎么办 包裹遗忘在郑州东站安检口了怎么办 锁书包的锁头钥匙全掉了怎么办 平板电脑恢复出厂设置变英语怎么办 给国外银行汇款账号写错账号怎么办