BZOJ3083——遥远的国度
1、题目大意:三个操作,换根,修改树上的某条路径,查询一个子树的最小值
2、分析:这个其实还是挺好做的,修改树上的某条路径,裸树剖,查询子树的最小值,这个是树剖满足dfs序
那么就是换根了,对吧,其实换根是o(1)的,就是root = u嘛。。。那么另两个操作就要变一变了,
那个修改路径是不变的,因为你不管怎么换根,树上的路径都是唯一的。。。这个结束
查询子树的最小值呢,分情况讨论,我分了三种 1.如果询问根,全询问,2.如果询问的是现在根的n辈祖先,
那么除了现在根的n-1辈祖先的那棵子树不询问以外,其余的都要查询3.否则就是原来的那棵子树
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define M 1000000 struct tree_chain_partition{ int Size[M], Top[M], Fa[M], value[M], num[M], Height[M], left[M], right[M]; int n; int root; int son[M], head[M], Next[M]; int tot, ST_tot; int q[M], lazy[M]; int tt[M][30]; void init(){ memset(lazy, -1, sizeof(lazy)); memset(head, -1, sizeof(head)); tot = ST_tot = 0; Top[1] = 1; } void pushdown(int o){ if(lazy[o] != -1){ q[2 * o] = q[2 * o + 1] = lazy[2 * o] = lazy[2 * o + 1] = lazy[o]; lazy[o] = -1; } } void add(int l, int r, int o, int x, int y, int k){ if(x <= l && r <= y){ q[o] = k; lazy[o] = k; return; } pushdown(o); int mid = (l + r) / 2; if(x <= mid) add(l, mid, 2 * o, x, y, k); if(y > mid) add(mid + 1, r, 2 * o + 1, x, y, k); q[o] = min(q[2 * o + 1], q[2 * o]); } int query(int l, int r, int o, int x, int y){ if(x > y) return 2147483647; if(x <= l && r <= y) return q[o]; pushdown(o); int mid = (l + r) / 2; int ret = 2147483647; if(x <= mid) ret = min(ret, query(l, mid, 2 * o, x, y)); if(y > mid) ret = min(ret, query(mid + 1, r, 2 * o + 1, x, y)); return ret; } inline void insert(int x, int y){ tot ++; son[tot] = y; Next[tot] = head[x]; head[x] = tot; } void dfs1(int x, int fa, int height){ Height[x] = height; Fa[x] = fa; for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){ dfs1(son[i], x, height + 1); Size[x] += Size[son[i]]; } Size[x] ++; } void dfs2(int x, int fa){ ST_tot ++; add(1, n, 1, ST_tot, ST_tot, value[x]); num[x] = ST_tot; left[x] = ST_tot; int o = 0, ss = 0; for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){ if(Size[son[i]] > ss){ o = i; ss = Size[son[i]]; } } if(o != 0){ Top[son[o]] = Top[x]; dfs2(son[o], x); } for(int i = head[x]; i != -1; i = Next[i]) if(o != i && son[i] != fa){ Top[son[i]] = son[i]; dfs2(son[i], x); } right[x] = ST_tot; } void init_lca(){ for(int i = 1; i <= n; i ++) tt[i][0] = Fa[i]; for(int i = 1; i <= 20; i ++){ for(int j = 1; j <= n; j ++){ tt[j][i] = tt[tt[j][i - 1]][i - 1]; } } } int zux(int x, int k){ for(int i = 0; i <= 20; i ++) if((1 << i) & k){ x = tt[x][i]; } return x; } bool is_(int x, int y){ if(Height[x] >= Height[y]) return false; if(zux(y, Height[y] - Height[x]) == x) return true; return false; } void add_root(int o){ root = o; } void real_add(int x, int y, int v){ while(Top[x] != Top[y]){ if(Height[Top[x]] < Height[Top[y]]) swap(x, y); add(1, n, 1, num[Top[x]], num[x], v); x = Fa[Top[x]]; } if(Height[x] < Height[y]) swap(x, y); add(1, n, 1, num[y], num[x], v); } int real_query(int x){ if(x == root){ return query(1, n, 1, left[1], right[1]); } else if(is_(x, root)){ int qt = zux(root, Height[root] - Height[x] - 1); return min(query(1, n, 1, left[1], left[qt] - 1), query(1, n, 1, right[qt] + 1, right[1])); } else{ return query(1, n, 1, left[x], right[x]); } } } wt; int main(){ int n, m; scanf("%d%d", &n, &m); wt.n = n; wt.init(); for(int i = 1; i < n; i ++){ int x, y; scanf("%d%d", &x, &y); wt.insert(x, y); wt.insert(y, x); } for(int i = 1; i <= n; i ++){ scanf("%d", &wt.value[i]); } scanf("%d", &wt.root); wt.dfs1(1, 0, 1); wt.dfs2(1, 0); wt.init_lca(); for(int i = 1; i <= m; i ++){ int op, x, y, z; scanf("%d", &op); if(op == 1){ scanf("%d", &x); wt.add_root(x); } else if(op == 2){ scanf("%d%d%d", &x, &y, &z); wt.real_add(x, y, z); } else{ scanf("%d", &x); printf("%d\n", wt.real_query(x)); } } return 0; }
BZOJ3083——遥远的国度的更多相关文章
- BZOJ3083 遥远的国度 【树链剖分】
BZOJ3083 遥远的国度 Description zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcw ...
- bzoj3083 遥远的国度 && bzoj3626 LCA (树链剖分)
今早刷了两道树剖的题目,用时两小时十五分钟= = 树剖的题目代码量普遍120+ 其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久 3083:裸树剖+"换根" ...
- [luogu3979][bzoj3083]遥远的国度
[luogu传送门] [bzoj传送门] 题目描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcww ...
- 2018.06.30 BZOJ3083: 遥远的国度(换根树剖)
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 512 MB Description 描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国 ...
- BZOJ3083 遥远的国度(树链剖分+线段树)
考虑暴力树剖.那么修改路径和查询子树最小值非常简单. 对于换根当然不能真的给他转一下,我们只记录当前根是哪个.对于查询,如果查询点不在当前根到原根的路径上,显然换根是对答案没有影响的:如果是当前根,答 ...
- 【树链剖分】【线段树】bzoj3083 遥远的国度
记最开始的根为root,换根之后,对于当前的根rtnow和询问子树U而言, ①rtnow==U,询问整棵树 ②fa[rtnow]==U,询问除了rtnow所在子树以外的整棵树 ③rtnow在U的子树里 ...
- BZOJ3083 遥远的国度 【树剖】
题目 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务 ...
- BZOJ3083: 遥远的国度
传送门 BZOJ100题辣(已经无法直视的正确率 树剖板子题,注意和dfs序结合,根据根的变化变换统计的方式即可. //BZOJ 3083 //by Cydiater //2016.10.23 #in ...
- bzoj3083 遥远的国度 题解
题目大意: 给定一棵有根树,每个点有一个权值,提供三种操作: 1.将x节点变为根节点 2.将x到y路径上的点的权值全部改为v 3.询问x的子树中点权的最小值 思路: 用DFS序剖分,记录每个节点入栈出 ...
随机推荐
- 《Java疯狂讲义》(第3版)学习笔记 1 - 如何学习Java
1.Java是一种面向对象语言,不要简单当做脚本使用.从基础学起,不要从Spring.J2EE.Hibernate和EJB开始学. 2.不要浮躁,应该扎扎实实先学好Java语言,然后按Java本身的学 ...
- 通过KUDU获取Azure网站的日志
部署到Azure上的website,由于无法通过RDP的方式去登录查看log,所以我们只能通过FTP的方式或者kudu的方式进行查看,具体如下: 1.使用FTP账户和密码登录网站的KUDU界面: 如您 ...
- Unity Particle System Sorting Order
http://answers.unity3d.com/questions/577288/particle-system-rendering-behind-sprites.html
- Mac下切换bash
MAC下的终端是神器,安装ZSH后,突然间发现太不好操作了,即使再配上oh-my-zsh也感觉不爽. 然后想删除,自己尝试了下找不到命令删除,于是在网上找找,但是也没找到.最后直接进隐藏文件夹,直接一 ...
- 网络框架 & 云端
Scut 傲瑞组件开发手册(02) -- 轻量级的通信引擎 StriveEngine http://blog.oraycn.com/StriveEngine.aspx
- border设置不占用宽度
经常我们设置好了DIV或其他标签的宽度,但是一加边框,宽度就又增加了,尤其是用百分比的时候,宽度控制不好真是麻烦! 如下有一解决办法,代码如下,(新属性,兼容性不好,手机端.谷歌.火狐测试可以) -w ...
- NoSQL 简介及什么是AICD
NoSQL 简介 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL". 在现代的计算系统上每天网络上都会产生庞大的数据量. 这些数据有很大一部分是由关 ...
- [webgrid] – selecterow - (Get Selected Row from ASP.NET MVC 3 WebGrid)
Get Selected Row from ASP.NET MVC 3 WebGrid Abstract: The following article demonstrates how to get ...
- js实现-下拉列表左右选择
下拉列表左右选择 * 下拉选择框 <select> <option>111</opt ...
- 自定义验证jquery.validate
js中填写 $(function() { validateSysConfigForm(); jQuery.validator.addMethod("validateNum", fu ...