bzoj3083遥远的国度(树链剖分+线段树)

Posted bztminamoto

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3083遥远的国度(树链剖分+线段树)相关的知识,希望对你有一定的参考价值。

题目描述

zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。

RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。

由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

输入输出格式

输入格式:

 

第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为根的子树中的最小防御值。

 

输出格式:

 

对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

 

输入输出样例

输入样例#1: 复制
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
输出样例#1: 复制
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

  然后发现没法维护子树信息,决定每一个点开一棵平衡树,后来发现空间要爆……

  于是好好学了一下正解

  首先查询和修改路径都是树剖的基本操作这里不提

  然后现在最重要的是换根操作咋整

  我们考虑一下,当前根与点$x$在原树中的关系无非以下几种:

  1.当前根就是点$x$——那么直接输出整棵树答案就行了

  2.当前根在原树中不在$x$的子树内——那么哪怕根换成了现在的根,$x$的子树还是没有变化,那么我们可以直接去原来的子树里查询

  3.当前根在原树中在$x$的子树内——那么我们设当前根在$u$点的子树$v$内,那么所要求的答案就是整棵树除去$v$这一棵子树的答案。至于怎么求$v$,可以从$root$往上跳重链,直到跳到$u$为止,那么就是看它从哪一个$u$点的子节点跳过来的就好了

  因为读入进来的时候路径端点和更改的值弄错了……而且忘记找$v$了……调了半天

  1 //minamoto
  2 #include<iostream>
  3 #include<cstdio>
  4 #define int unsigned int
  5 using namespace std;
  6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  7 char buf[1<<21],*p1=buf,*p2=buf;
  8 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
  9 inline int read(){
 10     #define num ch-‘0‘
 11     char ch;bool flag=0;int res;
 12     while(!isdigit(ch=getc()))
 13     (ch==-)&&(flag=true);
 14     for(res=num;isdigit(ch=getc());res=res*10+num);
 15     (flag)&&(res=-res);
 16     #undef num
 17     return res;
 18 }
 19 char sr[1<<21],z[30];int C=-1,Z;
 20 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
 21 inline void print(int x){
 22     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
 23     while(z[++Z]=x%10+48,x/=10);
 24     while(sr[++C]=z[Z],--Z);sr[++C]=
;
 25 }
 26 const int N=100005,inf=0xffffffff;
 27 int head[N],Next[N<<1],ver[N<<1],tot;
 28 int fa[N],dep[N],son[N],sz[N],top[N],ls[N],rs[N],cnt;
 29 int v[N],mn[N<<2],tag[N<<2];
 30 int n,m,rt;
 31 inline void add(int u,int v){
 32     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
 33     ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
 34 }
 35 void dfs1(int u){
 36     sz[u]=1,dep[u]=dep[fa[u]]+1;
 37     for(int i=head[u];i;i=Next[i]){
 38         int v=ver[i];
 39         if(v!=fa[u]){
 40             fa[v]=u,dfs1(v),sz[u]+=sz[v];
 41             if(sz[v]>sz[son[u]]) son[u]=v;
 42         }
 43     }
 44 }
 45 void dfs2(int u,int t){
 46     top[u]=t,ls[u]=++cnt;
 47     if(son[u]){
 48         dfs2(son[u],t);
 49         for(int i=head[u];i;i=Next[i]){
 50             int v=ver[i];
 51             if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
 52         }
 53     }
 54     rs[u]=cnt;
 55 }
 56 inline void pushup(int p){mn[p]=min(mn[p<<1],mn[p<<1|1]);}
 57 inline void pushdown(int p){
 58     if(tag[p])
 59     mn[p<<1]=mn[p<<1|1]=tag[p<<1]=tag[p<<1|1]=tag[p],tag[p]=0;
 60 }
 61 void build(int p,int l,int r){
 62     if(l==r) return (void)(mn[p]=v[l]);
 63     int mid=l+r>>1;
 64     build(p<<1,l,mid),build(p<<1|1,mid+1,r);
 65     pushup(p);
 66 }
 67 void update(int p,int l,int r,int ql,int qr,int x){
 68     if(ql<=l&&qr>=r) return (void)(mn[p]=tag[p]=x);
 69     pushdown(p);
 70     int mid=l+r>>1;
 71     if(ql<=mid) update(p<<1,l,mid,ql,qr,x);
 72     if(qr>mid) update(p<<1|1,mid+1,r,ql,qr,x);
 73     pushup(p);
 74 }
 75 int query(int p,int l,int r,int ql,int qr){
 76     if(ql<=l&&qr>=r) return mn[p];
 77     pushdown(p);
 78     int mid=l+r>>1,ans=inf;
 79     if(ql<=mid) cmin(ans,query(p<<1,l,mid,ql,qr));
 80     if(qr>mid) cmin(ans,query(p<<1|1,mid+1,r,ql,qr));
 81     return ans;
 82 }
 83 int find(int t,int u){
 84     while(top[u]!=top[t]){
 85         if(fa[top[u]]==t) return top[u];
 86         u=fa[top[u]];
 87     }
 88     return son[t];
 89 }
 90 void modify(int u,int v,int x){
 91     while(top[u]!=top[v]){
 92         if(dep[top[u]]<dep[top[v]]) swap(u,v);
 93         update(1,1,n,ls[top[u]],ls[u],x),u=fa[top[u]];
 94     }
 95     if(dep[u]>dep[v]) swap(u,v);
 96     update(1,1,n,ls[u],ls[v],x);
 97 }
 98 signed main(){
 99     //freopen("testdata.in","r",stdin);
100     n=read(),m=read();
101     for(int i=1;i<n;++i){
102         int u=read(),v=read();add(u,v);
103     }
104     dfs1(1),dfs2(1,1);
105     for(int i=1;i<=n;++i) v[ls[i]]=read();
106     build(1,1,n);
107     rt=read();
108     while(m--){
109         int opt=read(),x=read(),y,z;
110         switch(opt){
111             case 1:rt=x;break;
112             case 2:y=read(),z=read(),modify(x,y,z);break;
113             case 3:{
114                 if(ls[rt]==ls[x]) print(mn[1]);
115                 else if(ls[rt]<ls[x]||ls[rt]>rs[x]) print(query(1,1,n,ls[x],rs[x]));
116                 else{
117                     int res=inf,t=find(x,rt);
118                     if(ls[t]>1) cmin(res,query(1,1,n,1,ls[t]-1));
119                     if(rs[t]<n) cmin(res,query(1,1,n,rs[t]+1,n));
120                     print(res);
121                 }
122                 break;
123             }
124         }
125     }
126     Ot();
127     return 0;
128 }

 

以上是关于bzoj3083遥远的国度(树链剖分+线段树)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3083: 遥远的国度

BZOJ 3083 遥远的国度(树链剖分+LCA)

[日常摸鱼]bzoj3083遥远的国度-树链剖分

遥远的国度(树链剖分,换根)

bzoj3083 遥远的国度 题解

bzoj 1036 树链剖分+线段树 裸题