bzoj 3083 树链剖分
首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区间,后者询问区间的补集。
- /**************************************************************
- Problem: 3083
- User: BLADEVIL
- Language: C++
- Result: Accepted
- Time:6412 ms
- Memory:43904 kb
- ****************************************************************/
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #define maxn 200010
- #define maxm 400010
- #define inf (~0U>>1)
- using namespace std;
- struct segment_tree {
- int left,right,min_,lazy;
- }t[maxn<<];
- int n,m,l,rot,tot;
- int key[maxn];
- int other[maxm],pre[maxm],last[maxn];
- int size[maxn],max_son[maxn],top[maxn],dep[maxn],a[maxn],num[maxn][],jump[maxn][],dis[maxn];
- void connect(int x,int y) {
- pre[++l]=last[x];
- last[x]=l;
- other[l]=y;
- }
- void update(int x) {
- t[x].min_=min(t[x<<].min_,t[(x<<)+].min_);
- }
- void push_down(int x) {
- t[x<<].lazy=t[(x<<)+].lazy=t[x].lazy;
- t[x<<].min_=t[(x<<)+].min_=t[x].min_;
- t[x].lazy=;
- }
- int get_lca(int x,int y) {
- if (dis[x]>dis[y]) swap(x,y);
- int det=dis[y]-dis[x];
- for (int j=;j<=;j++) if (det&(<<j)) y=jump[y][j];
- if (x==y) return x;
- for (int j=;j>=;j--)
- if (jump[x][j]!=jump[y][j]) x=jump[x][j],y=jump[y][j];
- return jump[x][];
- }
- int get_lca_son(int x,int y) {
- if (dis[x]>dis[y]) swap(x,y);
- for (int j=;j>=;j--)
- if (dis[jump[y][j]]>dis[x]) y=jump[y][j];
- return y;
- }
- void dfs(int x) {
- size[x]=;
- for (int p=last[x];p;p=pre[p]) {
- if (dis[other[p]]) continue;
- jump[other[p]][]=x; dis[other[p]]=dis[x]+;
- dfs(other[p]);
- size[x]+=size[other[p]];
- if (size[other[p]]>size[max_son[x]]) max_son[x]=other[p];
- }
- }
- void make_segment(int x) {
- num[x][]=++tot; a[tot]=key[x];
- if (max_son[x]) {
- top[max_son[x]]=top[x];
- dep[max_son[x]]=dep[x];
- make_segment(max_son[x]);
- }
- for (int p=last[x];p;p=pre[p]) {
- if (other[p]==jump[x][]) continue;
- if (other[p]==max_son[x]) continue;
- top[other[p]]=other[p];
- dep[other[p]]=dep[x]+;
- make_segment(other[p]);
- }
- num[x][]=tot;
- }
- void build_segment(int x,int l,int r) {
- t[x].left=l; t[x].right=r;
- if (t[x].left==t[x].right) {
- t[x].min_=a[t[x].left];
- return ;
- }
- int mid=t[x].left+t[x].right>>;
- build_segment(x<<,l,mid); build_segment((x<<)+,mid+,r);
- update(x);
- }
- void change_segment_tree(int x,int l,int r,int y) {
- if (t[x].lazy) push_down(x);
- if ((t[x].left==l)&&(t[x].right==r)) {
- t[x].lazy=t[x].min_=y;
- return ;
- }
- int mid=t[x].left+t[x].right>>;
- if (l>mid) change_segment_tree((x<<)+,l,r,y); else
- if (r<=mid) change_segment_tree(x<<,l,r,y); else
- change_segment_tree(x<<,l,mid,y),change_segment_tree((x<<)+,mid+,r,y);
- update(x);
- }
- void change(int x,int y,int z) {
- if (dep[x]>dep[y]) swap(x,y);
- while (dep[x]!=dep[y]) {
- change_segment_tree(,num[top[y]][],num[y][],z);
- y=jump[top[y]][];
- }
- while (top[x]!=top[y]) {
- change_segment_tree(,num[top[x]][],num[x][],z);
- change_segment_tree(,num[top[y]][],num[y][],z);
- x=jump[top[x]][];
- y=jump[top[y]][];
- }
- if (num[x][]>num[y][]) swap(x,y);
- change_segment_tree(,num[x][],num[y][],z);
- }
- int query_segment_tree(int x,int l,int r) {
- if (l>r) return inf;
- if (t[x].lazy) push_down(x);
- if ((t[x].left==l)&&(t[x].right==r)) return t[x].min_;
- int mid=t[x].left+t[x].right>>;
- if (l>mid) return query_segment_tree((x<<)+,l,r); else
- if (r<=mid) return query_segment_tree(x<<,l,r); else
- return min(query_segment_tree(x<<,l,mid),query_segment_tree((x<<)+,mid+,r));
- }
- void query(int x) {
- if (x==rot) {
- printf("%d\n",t[].min_);
- return ;
- }
- if (get_lca(x,rot)!=x) printf("%d\n",query_segment_tree(,num[x][],num[x][])); else {
- int y=get_lca_son(x,rot);
- printf("%d\n",min(query_segment_tree(,,num[y][]-),query_segment_tree(,num[y][]+,n)));
- //printf("%d %d\n",query_segment_tree(1,1,num[y][0]-1),query_segment_tree(1,num[y][1]+1,n));
- //printf("%d\n",y);
- //printf("%d %d\n",num[y][0],num[y][1]);
- }
- }
- int main() {
- //freopen("country.in","r",stdin); freopen("country.out","w",stdout);
- scanf("%d%d",&n,&m);
- for (int i=;i<n;i++) {
- int x,y; scanf("%d%d",&x,&y);
- connect(x,y); connect(y,x);
- }
- for (int i=;i<=n;i++) scanf("%d",&key[i]);
- scanf("%d",&rot);
- dis[rot]=;
- dfs(rot);
- top[rot]=rot; dep[rot]=;
- make_segment(rot);
- //for (int i=1;i<=n;i++) printf("%d %d %d %d %d\n",i,max_son[i],size[i],num[i][0],num[i][1]);
- build_segment(,,n);
- for (int j=;j<=;j++)
- for (int i=;i<=n;i++) jump[i][j]=jump[jump[i][j-]][j-];
- while (m--) {
- int opt; scanf("%d",&opt);
- if (opt==) scanf("%d",&rot); else
- if (opt==) {
- int l,r,y; scanf("%d%d%d",&l,&r,&y);
- change(l,r,y);
- } else {
- int x; scanf("%d",&x);
- query(x);
- }
- }
- return ;
- }
bzoj 3083 树链剖分的更多相关文章
- BZOJ 3083 树链剖分+倍增+线段树
思路: 先随便选个点 链剖+线段树 1操作 就直接改root变量的值 2操作 线段树上改 3操作 分成三种情况 1.new root = xx 整个子树的min就是ans 2. lca(new roo ...
- BZOJ 4326 树链剖分+二分+差分+记忆化
去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! #include <iostream> #include <cstring> #i ...
- BZOJ 1036 && 树链剖分
还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...
- bzoj 2243 树链剖分
2013-11-19 16:21 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分,用线段树记录该区间的颜色段数,左右端点颜 ...
- bzoj 4196 树链剖分 模板
[Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2135 Solved: 1232[Submit][Status][D ...
- BZOJ 4811 树链剖分+线段树
思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...
- BZOJ 4034 树链剖分
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034 题意:中文题面 思路:树链剖分入门题. 剖分后就是一个简单的区间更新和区间求和问题. ...
- BZOJ 2286 树链剖分+DFS序+虚树+树形DP
第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...
- BZOJ 2836 树链剖分+线段树
思路: 链剖+线段树裸题 重链的标号就是DFS序 所以查子树的时候每回就 query(change[x],change[x]+size[x]-1) 就好了 剩下的应该都会吧.. //By Sirius ...
随机推荐
- JarvisOJ平台Web题部分writeup
PORT51 题目链接:http://web.jarvisoj.com:32770/ 这道题本来以为是访问服务器的51号端口,但是想想又不太对,应该是本地的51号端口访问服务器 想着用linux下的c ...
- BurpSuite 激活破解
1.下载软件关于Burp Suite, 它是进行Web应用安全测试的一个集成平台,无缝融合各种安全工具并提供全面的接口适配,支持完整的Web应用测试流程,从最初的映射和应用程序的攻击面分析到发现和利用 ...
- 2017 ACM Arabella Collegiate Programming Contest(solved 9/13, complex 12/13)
A.Sherlock Bones 题意: 给出长度为n的01串,问f(i,j)=f(j,k),(i<j<k)的i,j,k取值种数.其中f(i,j)表示[i,j]内1的个数, 且s[j]必须 ...
- 为什么我再也不想和 Google HR 交谈了
英文:yegor256,编译:伯乐在线/心灵是一棵开花的树 http://blog.jobbole.com/110340/ [伯乐在线导读]: 关于程序员面试时现场写代码,估计大家还记得 2015 年 ...
- 【BZOJ1923】外星千足虫(线性基)
[BZOJ1923]外星千足虫(线性基) 题面 BZOJ 洛谷 Description Input 第一行是两个正整数 N, M. 接下来 M行,按顺序给出 Charles 这M次使用"点足 ...
- Classical Binary Search
Find any position of a target number in a sorted array. Return -1 if target does not exist. 与题目 Firs ...
- redis的Pub/Sub功能
Pub/Sub功能(即Publish,Subscribe)意思是发布及订阅功能.简单的理解就像我们订阅blog一样,不同的是,这里的客户端与server端采用长连接建立推送机制,一个客户端发布消息,可 ...
- linux下shell显示-bash-3.2$ 不显示路径解决方法
linux操作下脚本不小心误删了很多东西,变成了下面的样子 在linux shell中不显示路径了,用起来很不方便. 如何改为显示路径的shell呢 步骤如下: vi ~/.bash_profi ...
- 【bzoj3669】魔法森林
Portal-->bzoj3669 Solution 愉悦智力康复ing 这题的话有两个比较关键的地方 首先是答案肯定是原图的某个生成树上的一条路径,那么我们考虑怎么来找这 ...
- struts2 - View页面中获取Action的成员变量
struts2 - View页面中获取Action的成员变量 2016年03月02日 11:04:44 IT男青年 阅读数:1074 View页面中获取Action的成员变量 按照Struts的设 ...