bzoj3083 遥远的国度 bzoj3626 LCA (树链剖分)
今早刷了两道树剖的题目,用时两小时十五分钟= =
树剖的题目代码量普遍120+
其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久
3083:裸树剖+“换根”
所谓换根其实只要判断一下当前询问点的子树和当前根的位置关系就好了,不能真的换根
根不在当前点的子树中则不影响;根在当前子树中,那么根所在的那部分子树不询问就可以了,而其他点都要询问
3626:这个题目很巧妙
有两个地方是很神的,一是将询问l~r转化为询问z一个点,二是离线操作O(qlog2n)就解决了询问
1 //bzoj3083 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 #define INF 1000000010 6 using namespace std; 7 const int maxn = 100010; 8 struct node{ 9 int l,r,lz,mn; 10 }t[maxn*4]; 11 struct edge{ 12 int to,next; 13 }e[maxn*2]; 14 int head[maxn],tot,n,Q,u,v,w,cap,size[maxn],fa[maxn],dep[maxn],top[maxn],son[maxn],tree[maxn],pre[maxn],cnt=0,v0[maxn],opt; 15 16 void insert(int u, int v){ 17 e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; 18 } 19 20 void dfs1(int u, int f, int d){ 21 size[u]=1; fa[u]=f; dep[u]=d; 22 for (int i=head[u]; i!=-1; i=e[i].next){ 23 int v=e[i].to; if (v==f) continue; 24 dfs1(v,u,d+1); 25 size[u]+=size[v]; 26 if (!son[u] || size[v]>size[son[u]]) son[u]=v; 27 } 28 } 29 30 void dfs2(int u, int num){ 31 top[u]=num; tree[u]=++cnt; pre[cnt]=u; 32 if (!son[u]) return; 33 dfs2(son[u],num); 34 for (int i=head[u]; i!=-1; i=e[i].next) 35 if (e[i].to!=fa[u] && e[i].to!=son[u]) dfs2(e[i].to,e[i].to); 36 } 37 38 void pushup(int x){ 39 t[x].mn=min(t[x<<1].mn,t[x<<1|1].mn); 40 } 41 42 void pushdown(int x){ 43 if (t[x].lz){ 44 t[x<<1].lz=t[x<<1|1].lz=t[x].lz; 45 t[x<<1].mn=t[x<<1|1].mn=t[x].mn; 46 t[x].lz=0; 47 } 48 } 49 50 void update(int a, int b, int w, int x){ 51 int l=t[x].l, r=t[x].r; 52 if (l==a && r==b){ 53 t[x].lz=1; 54 t[x].mn=w; 55 return; 56 } 57 int mid=l+r>>1; 58 pushdown(x); 59 if (a>mid) update(a,b,w,x<<1|1); 60 else if (b<=mid) update(a,b,w,x<<1); 61 else update(a,mid,w,x<<1),update(mid+1,b,w,x<<1|1); 62 pushup(x); 63 } 64 65 int get_min(int a, int b, int x){ 66 int l=t[x].l, r=t[x].r; 67 if (l==a && b==r) return t[x].mn; 68 int mid=l+r>>1; 69 pushdown(x); 70 if (b<=mid) return get_min(a,b,x<<1); 71 else if (a>mid) return get_min(a,b,x<<1|1); 72 else return min(get_min(a,mid,x<<1),get_min(mid+1,b,x<<1|1)); 73 } 74 75 void build(int l, int r, int x){ 76 t[x].l=l, t[x].r=r; 77 if (l==r){ 78 t[x].mn=v0[pre[l]]; 79 t[x].lz=0; 80 return; 81 } 82 int mid=l+r>>1; 83 if (l<=mid) build(l,mid,x<<1); 84 if (r>mid) build(mid+1,r,x<<1|1); 85 pushup(x); 86 } 87 88 void change(int x, int y, int c){ 89 while (top[x]!=top[y]){ 90 if (dep[x]<dep[y]) swap(x,y); 91 update(tree[top[x]],tree[x],c,1); 92 x=fa[top[x]]; 93 } 94 if (dep[x]>dep[y]) swap(x,y); 95 update(tree[x],tree[y],c,1); 96 } 97 98 int main(){ 99 scanf("%d%d", &n, &Q); tot=1; memset(head,-1,sizeof(head)); cnt=0; 100 for (int i=1; i<n; i++) scanf("%d%d", &u, &v),insert(u,v),insert(v,u); 101 dfs1(1,0,1); 102 dfs2(1,1); 103 for (int i=1; i<=n; i++) scanf("%d", &v0[i]); 104 build(1,cnt,1); 105 scanf("%d", &cap); 106 while (Q--){ 107 scanf("%d", &opt); 108 if (opt==1) scanf("%d", &cap); 109 if (opt==2){ 110 scanf("%d%d%d", &u, &v, &w); 111 change(u,v,w); 112 } 113 if (opt==3){ 114 scanf("%d", &u); 115 if (u==cap) printf("%d\n", t[1].mn); 116 else{ 117 int child=0; 118 for (int i=head[u]; i!=-1; i=e[i].next){ 119 int v=e[i].to; 120 if (v==fa[u]) continue; 121 if (tree[v]<=tree[cap] && tree[cap]<=tree[v]+size[v]-1) child=v; 122 } 123 if (child){ 124 int left=min(INF,get_min(1,tree[child]-1,1)); 125 int right=INF; 126 if (tree[child]+size[child]<=cnt) right=min(right,get_min(tree[child]+size[child],cnt,1)); 127 printf("%d\n", min(min(left,right),get_min(tree[u],tree[u],1))); 128 } 129 else printf("%d\n", get_min(tree[u],tree[u]+size[u]-1,1)); 130 } 131 } 132 } 133 return 0; 134 }
View Code
1 //bzoj3626 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 #define MOD 201314 6 using namespace std; 7 const int maxn = 50010; 8 struct node{ 9 int l,r,lz,sum,len; 10 }t[maxn*4]; 11 struct edge{ 12 int to,next; 13 }e[maxn*2]; 14 struct Ans{ 15 int z,R,L; 16 }ans[maxn]; 17 struct cover{ 18 int p,id; 19 bool flag; 20 }a[maxn*2]; 21 int fa[maxn],dep[maxn],size[maxn],top[maxn],son[maxn],head[maxn],tot,cnt; 22 int tree[maxn],pre[maxn],n,q,u,v; 23 24 bool cmp(cover a, cover b){ 25 return a.p<b.p; 26 } 27 28 void insert(int u, int v){ 29 e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; 30 } 31 32 void dfs1(int u, int f, int d){ 33 fa[u]=f; dep[u]=d; size[u]=1; 34 for (int i=head[u]; i!=-1; i=e[i].next){ 35 int v=e[i].to; if (v==f) continue; 36 dfs1(v,u,d+1); 37 size[u]+=size[v]; 38 if (!son[u] || size[v]>size[son[u]]) son[u]=v; 39 } 40 } 41 42 void dfs2(int u, int num){ 43 top[u]=num; tree[u]=++cnt; pre[cnt]=u; 44 if (!son[u]) return; 45 dfs2(son[u],num); 46 for (int i=head[u]; i!=-1; i=e[i].next) 47 if (e[i].to!=son[u] && e[i].to!=fa[u]) dfs2(e[i].to,e[i].to); 48 } 49 50 void pushup(int x){ 51 t[x].sum=t[x<<1].sum+t[x<<1|1].sum; 52 } 53 54 void pushdown(int x){ 55 if (t[x].lz){ 56 t[x<<1].lz+=t[x].lz; 57 t[x<<1|1].lz+=t[x].lz; 58 t[x<<1].sum+=t[x<<1].len*t[x].lz; 59 t[x<<1|1].sum+=t[x<<1|1].len*t[x].lz; 60 t[x].lz=0; 61 } 62 } 63 64 int query(int a, int b, int x){ 65 int l=t[x].l, r=t[x].r; 66 if (l==a && r==b) return t[x].sum; 67 int mid=l+r>>1; 68 pushdown(x); 69 if (b<=mid) return query(a,b,x<<1); 70 else if (a>mid) return query(a,b,x<<1|1); 71 else return query(a,mid,x<<1)+query(mid+1,b,x<<1|1); 72 } 73 74 void update(int a, int b, int x){ 75 int l=t[x].l, r=t[x].r; 76 if (l==a && r==b){ 77 t[x].sum+=t[x].len; 78 t[x].lz++; 79 return; 80 } 81 int mid=l+r>>1; 82 pushdown(x); 83 if (b<=mid) update(a,b,x<<1); 84 else if (a>mid) update(a,b,x<<1|1); 85 else update(a,mid,x<<1),update(mid+1,b,x<<1|1); 86 pushup(x); 87 } 88 89 void build(int l, int r, int x){ 90 t[x].l=l, t[x].r=r; t[x].len=r-l+1; 91 if (l==r){ 92 t[x].sum=0; 93 t[x].lz=0; 94 return; 95 } 96 int mid=l+r>>1; 97 if (l<=mid) build(l,mid,x<<1); 98 if (r>mid) build(mid+1,r,x<<1|1); 99 pushup(x); 100 } 101 102 void tree_update(int x, int y){ 103 while (top[x]!=top[y]){ 104 if (dep[x]<dep[y]) swap(x,y); 105 update(tree[top[x]],tree[x],1); 106 x=fa[top[x]]; 107 } 108 if (dep[x]>dep[y]) swap(x,y); 109 update(tree[x],tree[y],1); 110 } 111 112 int tree_query(int x, int y){ 113 int ret=0; 114 while (top[x]!=top[y]){ 115 if (dep[x]<dep[y]) swap(x,y); 116 ret+=query(tree[top[x]],tree[x],1); ret%=MOD; 117 x=fa[top[x]]; 118 } 119 if (dep[x]>dep[y]) swap(x,y); 120 return (query(tree[x],tree[y],1) % MOD +ret) % MOD; 121 } 122 123 int main(){ 124 scanf("%d%d", &n, &q); 125 tot=1; memset(head,-1,sizeof(head)); 126 for (int i=1; i<n; i++){ 127 scanf("%d", &u); 128 insert(u,i); 129 } 130 cnt=0; 131 dfs1(0,0,1); 132 dfs2(0,0); 133 build(1,n,1); 134 cnt=0; 135 for (int i=1; i<=q; i++){ 136 scanf("%d%d%d", &u, &v, &ans[i].z); 137 a[++cnt].p=u-1; a[cnt].id=i; a[cnt].flag=0; 138 a[++cnt].p=v; a[cnt].id=i; a[cnt].flag=1; 139 } 140 sort(a+1,a+1+cnt,cmp); 141 int now=-1; 142 for (int i=1; i<=cnt; i++){ 143 while (now<a[i].p){ 144 now++; 145 tree_update(now,0); 146 } 147 int pos=a[i].id; 148 if (!a[i].flag) ans[pos].L=tree_query(ans[pos].z,0); 149 else ans[pos].R=tree_query(ans[pos].z,0); 150 } 151 for (int i=1; i<=q; i++) printf("%d\n", (ans[i].R-ans[i].L+MOD)%MOD); 152 return 0; 153 }
View Code
转载于:https://www.cnblogs.com/mzl120918/p/5966291.html
bzoj3083 遥远的国度 bzoj3626 LCA (树链剖分)相关推荐
- BZOJ3626 LNOI2014 LCA 树链剖分
题意:给定一棵树,每次询问给出l r z,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和 题解: 显然,暴力求解的复杂度是无法承受的. 考虑这样的一种暴力,我们把 z 到根上的点全部打标 ...
- HDU - 6393 Traffic Network in Numazu(线段树+LCA+树链剖分+并查集)
题目链接:点击查看 题目大意:给出一个由n个点和n条边组成的图,每条边都有权值,题目保证图是连通的,然后给出m个询问,每次询问分为两种形式: 0 x y:将第x条边的权值修改为y 1 x y:查询x- ...
- CF613D-Kingdom and its Cities【虚树,LCA,树链剖分,贪心】
正题 题目链接:https://www.luogu.org/problem/CF613D 题目大意 一棵树,每次询问kkk个点,删除mmm个点要这些点两两不连通,求mmm的最小值. 解题思路 我们可以 ...
- HDU5266 LCA 树链剖分LCA 线段树
HDU5266 LCA Description 给一棵 n 个点的树,Q 个询问 [L,R] : 求点 L , 点 L+1 , 点 L+2 -- 点 R 的 LCA. Input 多组数据. The ...
- 数据结构课程设计-神秘国度的爱情故事-LCA:tarjan+离线/树链剖分/暴力
1.无脑暴力dfs: O(n*m) 2.LCA/tarjan+离线处理: O(n+m) 3.LCA/树链剖分: O(nlogn+m)~O(nlogn+mlogn) 4.LCA/倍增思想(有空再补) ...
- POJ - 1330 Nearest Common Ancestors(树上倍增/树链剖分求LCA)
题目链接:点击查看 题目大意:给出一棵有根树,我们需要求出两个点的lca 题目分析:因为题目说了是有根树,所以我们在建图的时候直接建有向图就好了,并且记录一下每个点的入度,建完图后找一下入度为0的点, ...
- jzoj3626-[LNOI2014]LCA【树链剖分,线段树】
正题 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3626 题目大意 一棵树,每次给出(l,r,z)(l,r,z)(l,r,z)询问∑i ...
- 【树链剖分】LCA(P4211)
正题 P4211 题目大意 给你一棵树,有m次询问,每次询问要回答∑i=lrdep[lca(x,i)]\sum_{i=l}^rdep[lca(x,i)]∑i=lrdep[lca(x,i)] 解题思路 ...
- bzoj 3626: [LNOI2014]LCA(离线差分+树链剖分)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MB Submit: 2885 Solved: 1133 [Submit][Sta ...
最新文章
- c++窗口管理系统是什么_优秀的食堂管理系统让你对校园生活更充满希望
- 生产环境一个like模糊匹配SQL优化
- wxWidgets:编写应用程序的快速指南
- java jtextarea 滚动条_java 在JTextArea中显示 滚动条
- JS获取移动端系统信息(操作系统、操作系统版本、横竖屏状态、设备类型、网络状态、生成浏览器指纹)...
- DB2 删除某用户下的所有表
- 酷安电脑版_2020年末 平板电脑购买推荐
- IoC 之 2.2 IoC 容器基本原理(贰)
- 掌握中台系统,需要了解哪些技术?
- DEDECMS安装遇到NO input files specified解决方案
- 作为一名优秀的软件测试工程师,需要具备哪些能力?
- debian 5常用软件包名称,及安装方法
- 如何把微信消息或者短信实时转发到另一个手机上
- JAVACC使用总结(四):LOOKAHEAD解决语法选择冲突的利刃
- 山峰和山谷 Ridges and Valleys
- AutoCAD Civil 3D坐标几何(COGO)输入
- 百度地图开发技术方案及解决办法
- 设计模式(四)行为型模式介绍及实例(上)
- Cache entry deserialization failed, entry ignored 错误解决
- ξσ Dicky's GuestBook σξ