BZOJ 3083 遥远的国度(树链剖分+LCA)
Description
描述
zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。
问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。
Input
第1行两个整数n m,代表城市个数和操作数。
第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
第n+1行,有n个整数,代表所有点的初始防御值。
第n+2行一个整数 id,代表初始的首都为id。
第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。
Output
对于每个opt=3的操作,输出一行代表对应子树的最小点权值。
Sample Input
3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1
Sample Output
1
2
3
4
提示
对于20%的数据,n<=1000 m<=1000。
对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。
题解:首先看到路径修改和子树查询,树链剖分就没得跑了,当然也可以写LCT
操作2/3用树剖自然好写,难的是一,换根怎么看怎么尬
想了一想,如果根就是询问点,子树就是整个区间
如果根在祖先,该点的子树不变.仍是按照正规的树剖查法查
如果根在询问点的任何一个子树中,那么该询问点的子树就变成了除了这个子树之外的所有区间.
主要是如何确定这个根在哪个子树中比较麻烦,写一个类似lca的玩意,倍增记录他的祖先,到时候一点点跳上去,复杂度还是可以接受的.
我一直以为是线段树写错了,果然做题太少了orz
代码如下:
- #include<cstdio>
- #include<vector>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #define lson root<<1
- #define rson root<<1|1
- #define inf 0x3f3f3f3f
- using namespace std;
- struct node
- {
- int lazy,m,l,r;
- } tr[];
- int n,deep[],son[],fa[],size[],id[],top[],c[],w[],cnt,rt;
- vector<int> g[];
- void push_up(int root)
- {
- tr[root].m=min(tr[lson].m,tr[rson].m);
- }
- void push_down(int root)
- {
- tr[lson].m=tr[root].lazy;
- tr[lson].lazy=tr[root].lazy;
- tr[rson].m=tr[root].lazy;
- tr[rson].lazy=tr[root].lazy;
- tr[root].lazy=inf;
- }
- void build(int root,int l,int r)
- {
- if(l==r)
- {
- tr[root].l=l;
- tr[root].r=r;
- tr[root].lazy=inf;
- tr[root].m=w[l];
- return ;
- }
- int mid=(l+r)>>;
- tr[root].l=l;
- tr[root].r=r;
- tr[root].lazy=inf;
- build(lson,l,mid);
- build(rson,mid+,r);
- push_up(root);
- }
- void update(int root,int l,int r,int val)
- {
- if(l==tr[root].l&&r==tr[root].r)
- {
- tr[root].lazy=val;
- tr[root].m=val;
- return ;
- }
- int mid=(tr[root].l+tr[root].r)>>;
- if(tr[root].lazy!=inf)
- {
- push_down(root);
- }
- if(l>mid)
- {
- update(rson,l,r,val);
- }
- else
- {
- if(r<=mid)
- {
- update(lson,l,r,val);
- }
- else
- {
- update(lson,l,mid,val);
- update(rson,mid+,r,val);
- }
- }
- push_up(root);
- }
- int query(int root,int l,int r)
- {
- if(l>r)
- {
- return inf;
- }
- if(tr[root].l==l&&tr[root].r==r)
- {
- return tr[root].m;
- }
- int mid=(tr[root].l+tr[root].r)>>;
- if(tr[root].lazy!=inf)
- {
- push_down(root);
- }
- if(l>mid)
- {
- return query(rson,l,r);
- }
- else
- {
- if(r<=mid)
- {
- return query(lson,l,r);
- }
- }
- return min(query(lson,l,mid),query(rson,mid+,r));
- }
- void dfs1(int now,int f,int dep)
- {
- deep[now]=dep;
- fa[now]=f;
- size[now]=;
- int maxson=-;
- for(int i=; i<g[now].size(); i++)
- {
- if(g[now][i]==f)
- {
- continue;
- }
- dfs1(g[now][i],now,dep+);
- size[now]+=size[g[now][i]];
- if(size[g[now][i]]>maxson)
- {
- son[now]=g[now][i];
- maxson=size[g[now][i]];
- }
- }
- }
- void dfs2(int now,int topf)
- {
- id[now]=++cnt;
- w[cnt]=c[now];
- top[now]=topf;
- if(!son[now])
- {
- return ;
- }
- dfs2(son[now],topf);
- for(int i=; i<g[now].size(); i++)
- {
- if(g[now][i]==fa[now]||g[now][i]==son[now])
- {
- continue;
- }
- dfs2(g[now][i],g[now][i]);
- }
- }
- void path_update(int x,int y,int val)
- {
- while(top[x]!=top[y])
- {
- if(deep[top[x]]<deep[top[y]])
- {
- swap(x,y);
- }
- update(,id[top[x]],id[x],val);
- x=fa[top[x]];
- }
- if(deep[x]>deep[y])
- {
- swap(x,y);
- }
- update(,id[x],id[y],val);
- }
- int sub_query(int x)
- {
- if(x==rt)
- {
- return query(,,cnt);
- }
- if(id[rt]<=id[x]+size[x]-&&id[rt]>=id[x])
- {
- return min(query(,,id[x]-),query(,id[x]+size[x],cnt));
- }
- return query(,id[x],id[x]+size[x]-);
- }
- int main()
- {
- int n,m;
- scanf("%d%d",&n,&m);
- for(int i=;i<=n-;i++)
- {
- int from,to;
- scanf("%d%d",&from,&to);
- g[from].push_back(to);
- g[to].push_back(from);
- }
- for(int i=;i<=n;i++)
- {
- scanf("%d",&c[i]);
- }
- scanf("%d",&rt);
- dfs1(rt,,);
- dfs2(rt,rt);
- build(,,n);
- int kd,ll,rr,vv;
- for(int i=;i<=m;i++)
- {
- scanf("%d",&kd);
- if(kd==)
- {
- scanf("%d",&vv);
- rt=vv;
- }
- if(kd==)
- {
- scanf("%d%d%d",&ll,&rr,&vv);
- path_update(ll,rr,vv);
- }
- if(kd==)
- {
- scanf("%d",&vv);
- printf("%d\n",sub_query(vv));
- }
- }
- }
BZOJ 3083 遥远的国度(树链剖分+LCA)的更多相关文章
- BZOJ 3083 遥远的国度 树链剖分
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- BZOJ 3083 遥远的国度 树链剖分+线段树
有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- BZOJ 3083 遥远的国度 树链剖分+脑子
唉..又调了半天QWQ..为何读入挂了.....莫非读入是反着的????据ywy学长所言如是...OvO震惊 这啥骚题啊...还要换根...不过清明讲过...(然鹅我现在才做... 先随便选个点(比如 ...
- bzoj 3083 遥远的国度 —— 树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 换根后路径还是不变,子树分类讨论一下,树剖后线段树维护即可. 代码如下: #inclu ...
- bzoj 3083 遥远的国度——树链剖分+线段树维护子树信息
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 int 的范围是 2^31 - 1 ,所以权值是不是爆 int 了…… O( nlog ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)
题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...
随机推荐
- Java 引用类型数组
引用类型变量可以使用类.接口或数组来声明. 数组引用变量是存放在栈内存(stack)中,数组元素是存放在堆内存(heap)中,通过栈内存中的指针指向对应元素在堆内存中的位置来实现访问. public ...
- 如何在已经安装好的Nginx上增加新模块
学习资源: https://blog.csdn.net/dxm2025/article/details/41149865 https://blog.csdn.net/qq_36663951/artic ...
- gitlab的本地搭建和部署使用
公司现在的代码管理是在公司的服务器上部署了gitlab,这样既方便协同开发,有可以很好的保护代码的安全性. 那么我们就来研究一下 如何给自己的服务器上部署gitlab吧! 学习源头:https://w ...
- Jenkins设置自动发邮件
安装Jenkins方法详解:https://www.cnblogs.com/lizhe860/p/9901257.html 一.设置全局变量 从首页依次进入系统工具→系统设置 二.在项目配置中设置项目 ...
- python学习(十七) 扩展python
c, c++, java比python快几个数量级. 17.1 考虑哪个更重要 开发速度还是运行速度更重要. 17.2 非常简单的途径:Jython和IronPython Jython可以直接访问JA ...
- [原创]Java使用反射及自定义注解实现对象差异性比较
Java项目C中 有一处逻辑,对于资源数据(类型为ResourceItem,拥有int/double/boolean/String类型数十个字段),需要比对资源数据每次变更的差异,并描述出变更情况.并 ...
- Android Studio 配置模拟器AVD存放路径(默认在c盘,解决c盘空间不够问题)
Android Studio 安装之后,默认的会给我们创建一个 Nexus 的模拟器, 这个模拟器的镜像文件放在了 C:\Users\Administrator\.android 中 其中的avd文 ...
- [JBPM3.2]TaskNode的signal属性详解
TaskNode节点的signal属性决定了任务完成时对流程执行继续的影响,共有六种取值:unsynchronized,never,first,first-wait,last,last-wait.默认 ...
- Scala语言简介和开发环境配置
Scala语言的简介和开发环境搭建 Scala是一门结合了面向对象特征和函数式编程特征的语言,它是一个创新的编程语言产品.Scala可以做脚本(就像shell脚本一样),可以做服务端编程语言,可以写数 ...
- go语言 robfig/cron包 实现定时 调用
package main import ( "github.com/robfig/cron" "time" "fmt" "os&q ...