樹剖+線段樹+dfs序+LCA--bzoj3083 遙遠的國度
阿新 • • 發佈:2018-11-25
傳送門
一道樹剖線段樹維護
序的好題,首先換根的時候考慮一個點的子樹的變化,分類討論:
設當前根為
,詢問點為
所以在第三種情況的時候只需要倍增求出
,
答案就是
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ls cur<<1
#define rs cur<<1|1
#define N 100005
#define inf 0x7fffffff
using namespace std;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
int n,m,val[N],dfn[N],f[N],dep[N],siz[N],son[N],rk[N],top[N];
int num,cnt,head[N],root,opt,prert,g[N][18];
struct EDGE{
int to,nxt;
}edge[N<<1];
inline void add(int x,int y){
edge[++cnt].to=y; edge[cnt].nxt=head[x]; head[x]=cnt;
}
void dfs1(int u,int fa){
siz[u]=1; int maxson=-1;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa) continue;
dep[v]=dep[u]+1; f[v]=u; g[v][0]=u;
for(int j=1;j<=17;j++)
g[v][j]=g[g[v][j-1]][j-1];
dfs1(v,u); siz[u]+=siz[v];
if(siz[v]>maxson) maxson=siz[v],son[u]=v;
} return;
}
void dfs2(int u,int t){
dfn[u]=++num; rk[num]=u; top[u]=t;
if(!son[u]) return;
dfs2(son[u],t);
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(!dfn[v]) dfs2(v,v);
} return;
}
struct Node{
int l,r,mn,lazy;
}node[N<<2];
inline void pushup(int cur){
node[cur].mn=min(node[ls].mn,node[rs].mn);
}
inline void pushdown(int cur){
if(node[cur].lazy){
node[ls].mn=node[rs].mn=node[ls].lazy=node[rs].lazy=node[cur].lazy;
node[cur].lazy=0;
}
}
void build(int cur,int L,int R){
if(L==R){
node[cur].l=node[cur].r=L; node[cur].mn=val[rk[L]];
return ;
}
int mid=(L+R)>>1;
build(ls,L,mid); build(rs,mid+1,R);
node[cur].l=node[ls].l,node[cur].r=node[rs].r;
pushup(cur); return;
}
void update(int cur,int L,int R,int c){
if(L<=node[cur].l && node[cur].r<=R){
node[cur].mn=c; node[cur].lazy=c;
return;
}
pushdown(cur);
int mid=(node[cur].l+node[cur].r)>>1;
if(L<=mid) update(ls,L,R,c);
if(mid<R) update(rs,L,R,c);
pushup(cur); return;
}
int query(int cur,int L,int R){
if(L<=node[cur].l && node[cur].r<=R) return node[cur].mn;
pushdown(cur);
int mid=(node[cur].l+node[cur].r)>>1,res=inf;
if(L<=mid) res=min(res,query(ls,L,R));
if(mid<R) res=min(res,query(rs,L,R));
return res;
}
inline void change(int x,int y,int c){
while(top[x]!=top[y]){
if(dep[top[x]]<=dep[top[y]]) swap(x,y);
update(1,dfn[top[x]],dfn[x],c);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(1,dfn[x],dfn[y],c); return;
}
inline int ask(int x,int y){
int res=inf;
while(top[x]!=top[y]){
if(dep[top[x]]<=dep[top[y]]) swap(x,y);
res=min(res,query(1,dfn[top[x]],dfn[x]));
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
res=min(res,query(1,dfn[x],dfn[y]));
return res;
}
inline int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>=dep[top[y]]) x=f[top[x]];
else y=f[top[y]];
}
return dep[x]<dep[y]?x:y;
}
inline int find(int x,int len){
for(int i=0;i<=17;i++)
if(len&(1<<i)) x=g[x][i];
return x;
}
inline int solve(int x){
if(x==root) return query(1,1,n);
if(dfn[x]>=dfn[root] && dfn[x]<=dfn[root]+siz[root]-1)
return query(1,dfn[x],dfn[x]+siz[x]-1);
if(LCA(x,root)==x){
int y=find(root,dep[root]-dep[x]-1);
return min(query(1,1,dfn[y]-1),query(1,dfn[y]+siz[y],n));
}
return query(1,dfn[x],dfn[x]+siz[x]-1);
}
int main(){
n=rd(); m=rd();
for(int i=1;i<n;i++){
int x=rd(),y=rd();
add(x,y); add(y,x);
}
for(int i=1;i<=n;i++) val[i]=rd();
prert=root=rd(); dfs1(root