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序剖分,记录每个节点入栈出 ...
随机推荐
- 初识PHP
初识PHP 虽然是做前端的,可是平时看书.做项目都会与后端PHP相关,但却不是很了解,并经常听PHP大神说:PHP是世界上最好的语言!因此,通过这篇博文学习.总结PHP,来认识认识这个“世界上最好的语 ...
- 把ISO文件加载到虚拟光驱
1. 下载迅雷 2. 介绍一个下载微软产品的网站(I tell you),里面的下载程序都是破解好的罗.http://www.itellyou.cn/ 3. 在"I tell you&q ...
- 转: CvMat,Mat和IplImage之间的转化和拷贝
1.CvMat之间的复制 //注意:深拷贝 - 单独分配空间,两者相互独立 CvMat* a; CvMat* b = cvCloneMat(a); //copy a to b 2.Mat之间的复制 / ...
- Struts2入门-十分简单的登陆
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互. 开始编写St ...
- 转换流——OutputStreamWriter类与InputStreamReader类
字节流和字符流的转换类 OutputStreamWriter:是Writer的子类,将输出的字符流变成字节流 InputStreamReader:是Reader的子类,将输入的字节流变成字符流 将字节 ...
- 一张图总结docker命令
- 微信H5手指滑动屏蔽微信的默认效果
我们的H5页面放在微信上时,如果你向上滑动或者向下滑动屏幕时,会发现一些微信的特征,譬如:网页由www.baidu.com提供. 去掉这个微信的特征,代码如下: var f; n.addEventLi ...
- Effective Objective-C 2.0 — 第12条:理解消息转发机制
11 条讲解了对象的消息传递机制 12条讲解对象在收到无法解读的消息之后会发生什么,就会启动“消息转发”(message forwarding)机制, 若对象无法响应某个选择子,则进入消息转发流程. ...
- springmvc请求参数获取的几种方法
1.直接把表单的参数写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交. /** * 1.直接把表单的参数写在Controller相应的方法的形参中 * @pa ...
- struts2进阶篇(2)
一.Action与MVCstruts2是一个基于MVC的web应用框架,它将应用程序分为三个组件:模型,视图,控制器.模型:包含了应用程序的业务逻辑和业务数据,由封装数据和处理业务的javaBean组 ...