P3979 遥远的国度
P3979 遥远的国度
思路
一开始我用这个函数得到左端点
int get_l(int x,int y) {
if(top[x]==top[y]) return son[x];
int last=top[x];
while(top[x]!=top[y]) {
last=top[x];
x=fa[top[x]];
}
if(x==y) return last;
return son[x];
}
发现是错误的
无奈数据太水,还90,bzoj也错了一个点
debug了一上午
到现在我也不知道哪里错了,各路好汉看看吧
也许是我没用dfs序的性质吧
x的儿子点一定在x的子树范围内child[x] ---- child[x]+siz[child[x]]-1
代码
#include <bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=5e5+7;
const int inf=0x7fffffff;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,w[maxn];
int dep[maxn],son[maxn],fa[maxn],siz[maxn];
int a[maxn],idx[maxn],top[maxn],cnt;
struct node {
int v,nxt;
}e[maxn<<1];
int head[maxn<<1],tot;
void add_edge(int u,int v) {
e[++tot].v=v;
e[tot].nxt=head[u];
head[u]=tot;
}
namespace seg_tree {
struct node {
int l,r,lazy,mi;
}e[maxn<<2];
void pushup(int rt) {
e[rt].mi=min(e[ls].mi,e[rs].mi);
}
void pushdown(int rt) {
if(e[rt].lazy) {
e[ls].mi=e[rs].mi=e[rt].lazy;
e[ls].lazy=e[rs].lazy=e[rt].lazy;
e[rt].lazy=0;
}
}
void build(int l,int r,int rt) {
e[rt].l=l,e[rt].r=r;
if(l==r) {
e[rt].mi=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
pushup(rt);
}
void modify(int L,int R,int k,int rt) {
if(L<=e[rt].l&&e[rt].r<=R) {
e[rt].mi=e[rt].lazy=k;
return;
}
pushdown(rt);
int mid=(e[rt].l+e[rt].r)>>1;
if(L<=mid) modify(L,R,k,ls);
if(R>mid) modify(L,R,k,rs);
pushup(rt);
}
int query(int L,int R,int rt) {
if(R<e[rt].l||e[rt].r<L) return inf;
if(L<=e[rt].l&&e[rt].r<=R) return e[rt].mi;
pushdown(rt);
int mid=(e[rt].l+e[rt].r)>>1;
int ans=inf;
if(L<=mid) ans=min(ans,query(L,R,ls));
if(R>mid) ans=min(ans,query(L,R,rs));
return ans;
}
}
void dfs1(int u,int f) {
siz[u]=1;
fa[u]=f;
son[u]=0;
dep[u]=dep[f]+1;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v==f) continue;
dfs1(v,u);
if(siz[v] > siz[son[u]]) son[u]=v;
siz[u]+=siz[v];
}
}
void dfs2(int u,int ttt) {
idx[u]=++cnt;
a[cnt]=w[u];
top[u]=ttt;
if(!son[u]) return;
dfs2(son[u],ttt);
for(int i=head[u];i;i=e[i].nxt) {
if(!idx[e[i].v])
dfs2(e[i].v,e[i].v);
}
}
void CHANGE(int x,int y,int z) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
seg_tree::modify(idx[top[x]],idx[x],z,1);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
seg_tree::modify(idx[x],idx[y],z,1);
}
int lca(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<=dep[y] ? x : y;
}
int main() {
n=read(),m=read();
FOR(i,2,n) {
int x=read(),y=read();
add_edge(x,y),add_edge(y,x);
}
FOR(i,1,n) w[i]=read();
int rt=read();
dfs1(1,0);
dfs2(1,1);
seg_tree::build(1,n,1);
FOR(i,1,m) {
int opt=read();
if(opt==1) {
rt=read();
} else if(opt==2) {
int x=read(),y=read(),v=read();
CHANGE(x,y,v);
} else if(opt==3) {
int x=read();
if(rt==x) {
cout<<seg_tree::e[1].mi<<"\n";
continue;
}
int tmp=lca(x,rt);
if(tmp!=x) {
cout<<seg_tree::query(idx[x],idx[x]+siz[x]-1,1)<<"\n";
} else {
int l;
for(int i=head[x];i;i=e[i].nxt) {
int v=e[i].v;
if(idx[v]<=idx[rt]&&idx[v]+siz[v]-1>=idx[rt]){
l=v;
break;
}
}
int r=l+siz[l];
int ans1=inf,ans2=inf;
ans1=seg_tree::query(1,idx[l]-1,1);
ans2=seg_tree::query(idx[l]+siz[l],n,1);
cout<<min(ans1,ans2)<<"\n";
}
}
}
return 0;
}