SPOJ 375 query on a tree 树链剖分
题意:
给一棵树型数据结构
①支持修改边的权值 ②支持成段边权最值查询
树链剖分入门题、
树链剖分+线段树
用的notonlysuccess的线段树——不开结构体事先预处理的那种
我以前写的都是结构体的那种~
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cstring> 6 7 //notonlysuccess版线段树-树链剖分 8 9 #define N 20010 10 11 using namespace std; 12 13 int d[N][3]; 14 int to[N<<1],next[N<<1]; 15 int mx[N]; 16 int root,tot,cnt,n,m,cas; 17 int head[N],dep[N],wnum[N],fa[N],top[N],son[N],sz[N]; 18 //sz[x]树的大小 dep[x]深度 top[x] x所在重路径中深度最小的点 fa[x]父亲节点 son[x]重儿子 wnum[x] x与其父亲之间的边的编号 19 20 inline void add(int u,int v) 21 { 22 to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++; 23 } 24 25 inline void dfs(int x)//dfs求出fa[x],son[x],dep[x],sz[x] 26 { 27 sz[x]=1; son[x]=0; 28 for(int i=head[x];~i;i=next[i]) 29 if(fa[x]!=to[i]) 30 { 31 fa[to[i]]=x; 32 dep[to[i]]=dep[x]+1; 33 dfs(to[i]); 34 if(sz[to[i]]>sz[son[x]]) son[x]=to[i];//重边 35 sz[x]+=sz[to[i]]; 36 } 37 } 38 39 inline void build(int x,int fx)//求出top[x],wnum[x](边的编号) 40 { 41 wnum[x]=++tot; top[x]=fx; 42 if(son[x]!=0) build(son[x],top[x]);//保证重边边权相连 43 for(int i=head[x];~i;i=next[i]) 44 if(to[i]!=son[x]&&to[i]!=fa[x]) build(to[i],to[i]); 45 } 46 47 inline void updata(int x,int lt,int rt,int wn,int w) 48 { 49 if(wn>rt||wn<lt) return; 50 if(lt==rt) {mx[x]=w; return;} 51 int mid=(lt+rt)>>1; 52 int ls=x<<1,rs=ls+1; 53 updata(ls,lt,mid,wn,w); 54 updata(rs,mid+1,rt,wn,w); 55 mx[x]=max(mx[ls],mx[rs]); 56 } 57 58 inline int maxlen(int x,int lt,int rt,int l,int r)//求边的编号在[l,r]之间的最大边权 59 { 60 if(l>rt||r<lt) return 0; 61 if(l<=lt&&rt<=r) return mx[x]; 62 int mid=(lt+rt)>>1; 63 int ls=x<<1,rs=ls+1; 64 return max(maxlen(ls,lt,mid,l,r),maxlen(rs,mid+1,rt,l,r)); 65 } 66 67 inline int query(int x,int y) 68 { 69 int fx=top[x],fy=top[y],ans=0; 70 while(fx!=fy) 71 { 72 if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy); 73 ans=max(ans,maxlen(1,1,tot,wnum[fx],wnum[x])); 74 x=fa[fx]; fx=top[x]; 75 } 76 if(x==y) return ans; 77 if(dep[x]>dep[y]) swap(x,y); 78 return max(ans,maxlen(1,1,tot,wnum[son[x]],wnum[y])); 79 } 80 81 inline void read() 82 { 83 scanf("%d",&n); 84 root=(n+1)>>1; 85 fa[root]=dep[root]=cnt=tot=0; 86 memset(sz,0,sizeof sz); 87 memset(head,-1,sizeof head); 88 memset(mx,0,sizeof mx); 89 for(int i=1;i<n;i++) 90 { 91 scanf("%d%d%d",&d[i][0],&d[i][1],&d[i][2]); 92 add(d[i][0],d[i][1]); 93 add(d[i][1],d[i][0]); 94 } 95 dfs(root); 96 build(root,root); 97 for(int i=1;i<n;i++) 98 { 99 if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]); 100 updata(1,1,tot,wnum[d[i][1]],d[i][2]); 101 } 102 } 103 104 inline void go() 105 { 106 char str[10]; int a,b; 107 while(true) 108 { 109 scanf("%s",str); 110 if(str[0]=='D') return; 111 scanf("%d%d",&a,&b); 112 if(str[0]=='Q') printf("%d\n",query(a,b)); 113 else updata(1,1,tot,wnum[d[a][1]],b); 114 } 115 } 116 117 int main() 118 { 119 scanf("%d",&cas); 120 while(cas--) read(),go(); 121 return 0; 122 }
又写了一发,和之前风格完全不同。。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <algorithm> 6 7 #define N 100000 8 #define M 200000 9 #define INF 1e9 10 11 using namespace std; 12 13 int head[N],next[M],to[M],len[M]; 14 int son[N],fa[N],dat[M],bh[M],pre[N],dep[N],sz[N],top[N]; 15 int q[N],mx[M<<2]; 16 int n,cnt,tot; 17 18 inline void add(int u,int v,int w) 19 { 20 to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; 21 } 22 23 inline void init() 24 { 25 memset(son,-1,sizeof son); 26 memset(fa,0,sizeof fa); 27 memset(head,-1,sizeof head); cnt=0; 28 tot=0; 29 } 30 31 inline void prep() 32 { 33 int h=1,t=2,sta; 34 q[1]=1; dep[1]=1; 35 while(h<t) 36 { 37 sta=q[h++]; sz[sta]=1; 38 for(int i=head[sta];~i;i=next[i]) 39 if(fa[sta]!=to[i]) 40 { 41 fa[to[i]]=sta; 42 dep[to[i]]=dep[sta]+1; 43 pre[to[i]]=len[i]; 44 q[t++]=to[i]; 45 } 46 } 47 for(int j=t-1;j>=1;j--) 48 { 49 sta=q[j]; 50 for(int i=head[sta];~i;i=next[i]) 51 if(fa[sta]!=to[i]) 52 { 53 sz[sta]+=sz[to[i]]; 54 if(son[sta]==-1||sz[to[i]]>sz[to[son[sta]]]) son[sta]=i; 55 } 56 } 57 for(int i=1;i<t;i++) 58 { 59 sta=q[i]; 60 if(to[son[fa[sta]]]==sta) top[sta]=top[fa[sta]]; 61 else top[sta]=sta; 62 } 63 } 64 65 inline void rewrite() 66 { 67 for(int i=1;i<=n;i++) 68 if(top[i]==i) 69 for(int j=son[i];~j;j=son[to[j]]) 70 { 71 bh[(j>>1)+1]=++tot; 72 dat[tot]=len[i]; 73 } 74 } 75 76 inline void pushup(int u) 77 { 78 mx[u]=max(mx[u<<1],mx[u<<1|1]); 79 } 80 81 inline void build(int u,int L,int R) 82 { 83 if(L==R) {mx[u]=dat[L];return;} 84 int MID=(L+R)>>1; 85 build(u<<1,L,MID); build(u<<1|1,MID+1,R); 86 pushup(u); 87 } 88 89 inline void read() 90 { 91 init(); 92 scanf("%d",&n); 93 for(int i=1,a,b,c;i<n;i++) 94 { 95 scanf("%d%d%d",&a,&b,&c); 96 add(a,b,c); add(b,a,c); 97 } 98 99 prep(); 100 rewrite(); 101 build(1,1,tot); 102 } 103 104 inline void updata(int u,int L,int R,int pos,int sp) 105 { 106 if(L==R) {mx[u]=sp;return;} 107 int MID=(L+R)>>1; 108 if(pos<=MID) updata(u<<1,L,MID,pos,sp); 109 else updata(u<<1|1,MID+1,R,pos,sp); 110 pushup(u); 111 } 112 113 inline int querymax(int u,int L,int R,int l,int r) 114 { 115 if(l<=L&&R<=r) return mx[u]; 116 int MID=(L+R)>>1,res=-INF; 117 if(l<MID) res=max(res,querymax(u<<1,L,MID,l,r)); 118 if(MID<r) res=max(res,querymax(u<<1|1,MID+1,R,l,r)); 119 return res; 120 } 121 122 inline int getmax(int x,int y) 123 { 124 int res=-INF; 125 while(top[x]!=top[y]) 126 { 127 if(dep[top[x]]<dep[top[y]]) swap(x,y); 128 res=max(res,querymax(1,1,tot,bh[top[x]],bh[x])); 129 res=max(res,pre[top[x]]); 130 x=fa[top[x]]; 131 } 132 if(bh[x]>bh[y]) swap(x,y); 133 res=max(res,querymax(1,1,tot,bh[x],bh[y])); 134 return res; 135 } 136 137 inline void go() 138 { 139 char str[10];int a,b; 140 while(scanf("%s",str)) 141 { 142 if(str[0]=='D') break; 143 scanf("%d%d",&a,&b); 144 if(str[0]=='C') updata(1,1,tot,bh[a],b); 145 else printf("%d\n",getmax(a,b)); 146 } 147 } 148 149 int main() 150 { 151 int cas;scanf("%d",&cas); 152 while(cas--) read(),go(); 153 return 0; 154 }
转载于:https://www.cnblogs.com/proverbs/archive/2013/01/02/2842572.html
SPOJ 375 query on a tree 树链剖分相关推荐
- SPOJ - QTREE Query on a tree(树链剖分+线段树)
题目链接:点击查看 题目大意:给出一棵由n个点组成的树,再给出数个操作,每次操作分为下列几种类型: QUERY x y:询问点x-点y这条路径上的所有边权的最大值 CHANGE x y:将第x条边的权 ...
- HDU - 3804 Query on a tree(树链剖分+线段树+离线处理)
题目链接:点击查看 题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1: 题目分析: ...
- SPOJ Query on a tree 树链剖分 边修改
链接 提交链接 题解 对边的修改算到点上 只需要修改下面的地方 代码 #include<bits/stdc++.h> #define N 10010 #define INF 0x3f3f3 ...
- SPOJ 375. Query on a tree (树链剖分)
题目链接: http://www.spoj.com/problems/QTREE/ 375. Query on a tree Problem code: QTREE You are given a t ...
- spoj 375 Query on a tree (树链剖分)
题目链接: http://www.spoj.com/problems/QTREE/ 题意: 给一颗树,每条边有一个权值.有两种操作: 1.修改某条边的值: 2.询问a.b两点路径上边权的最大值. 分析 ...
- spoj 375 Query on a tree
题意:给一棵树,节点数不超过10000,有两个操作:1.询问a,b路径上最长的边长.2.把第a条边长度改为b. p.s.人生中第一个树链剖分,尼玛debug了好久好久我擦... 分析:轻重边路径剖分, ...
- POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘...
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12247 Accepted: 3151 Descriptio ...
- CodeForces - 343D Water Tree(树链剖分+线段树)
题目链接: 题目大意:给出一棵由n个点组成的树,初始时每个点的权值为0,接下来有m个操作,每个操作分为以下三种: 1 x:将包括节点x在内的所有子孙节点的权值都改为1 2 x:将包括节点x在内的所有父 ...
- 计蒜客 - Distance on the tree(树链剖分+离线处理+线段树)
题目链接:点击查看 题目大意:给出一颗含有n个节点的树,每条边都有权值,现在给出m个询问,每次询问的格式为u,v,w,我们需要求出在路径u-v上,边权小于等于w的边的个数 题目分析:因为一开始不会主席 ...
最新文章
- spring集成 JedisCluster 连接 redis3.0 集群
- Linux mysql federated_MySQL的FEDERATED引擎实现类Oracle的DBlink
- Java魔法堂:初探MessageFormat.format和ChoiceFormat
- mac 用户 文件夹 权限_Mac视频播放软件推荐
- C语言——二分法查找一个数_数组
- Java复习第三天-静态方法
- linux部署python web_在linux上部署web环境
- asp.net下Response.ContentType类型汇总
- LibSvm使用说明和LibSvm源码解析
- 图形数据库 Neo4j(2) ----Java
- 学qt的都干什么工作_【板绘前景】学板绘可以干什么工作?学多久才可以工作?好学吗?...
- HashMap的实现原理、JDK1.7和JDK1.8的对比以及死锁问题
- 优卡仕广告一体机——商用显示设备专家
- 高斯-约当消元法(转)
- 回归预测分析(RANSAC、多项式回归、残差图、随机森林)
- 魔兽世界linux客户端,使用Wine在Linux下玩魔兽世界
- 初中数学结合计算机教学设计,初中数学教学设计中多媒体技术的运用
- 一文读懂谷歌I/O 新硬件、Android Q及多项功能升级
- linux图形界面介绍
- String intern驻足
热门文章
- 【物联网】QCA4010之SNTP协议
- Struts 2基础
- python3网络爬虫开发实战下载_【Python3网络爬虫开发实战】 1.1-Python3的安装
- java里的主线程和子线程以及finally不会执行的特殊情况
- python中items属性的用法
- jsp ajax三级联动,Spring MVC+JSP实现三级联动
- VC各种情况下的窗口句柄的获取
- pixhawk的姿态控制算法解读
- define宏定义和const定义之间的区别
- Codeforces Round #529 (Div. 3) E. Almost Regular Bracket Sequence (括号配对,前缀和)