天天看點

bzoj3083 遙遠的國度 樹鍊剖分+lcaDescriptionSolutionCode

Description

zcwwzdjn在追殺十分sb的zhx,而zhx逃入了一個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神RapiD阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。

問題是這樣的:遙遠的國度有n個城市,這些城市之間由一些路連接配接且這些城市構成了一顆樹。這個國度有一個首都,我們可以把這個首都看做整棵樹的根,但遙遠的國度比較奇怪,首都是随時有可能變為另外一個城市的。遙遠的國度的每個城市有一個防禦值,有些時候RapiD會使得某兩個城市之間的路徑上的所有城市的防禦值都變為某個值。RapiD想知道在某個時候,如果把首都看做整棵樹的根的話,那麼以某個城市為根的子樹的所有城市的防禦值最小是多少。由于RapiD無法解決這個問題,是以他攔住了zcwwzdjn希望他能幫忙。但zcwwzdjn還要追殺sb的zhx,是以這個重大的問題就被轉交到了你的手上。

對于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。

Solution

顯然是不能暴力換根的

先以1為預設根做一遍剖分,記查詢點為x,目前根為root,若lca(root,x)!=x就該怎麼做怎麼做,否則需要去掉x的子樹中包含root的那個再查詢

root=x特判整棵樹都要做

一開始少打else搞得輸入挂掉了,re半頁

Code

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
const int INF=;
const int N=;
const int E=;
using std:: swap;
struct edge{int x,y,next;}e[E];
int a[N],size[N],fa[N][],bl[N],dep[N],pos[N];
int mn[N<<],lazy[N<<];
int ls[N],edCnt=,n,m;
int read() {
    int x=,v=; char ch=getchar();
    for (;ch<'0'||ch>'9';v=(ch=='-')?(-):(v),ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*+ch-'0',ch=getchar());
    return x*v;
}
void addEdge(int x,int y) {
    e[++edCnt]=(edge){x,y,ls[x]}; ls[x]=edCnt;
    e[++edCnt]=(edge){y,x,ls[y]}; ls[y]=edCnt;
}
void push_down(int now,int tl,int tr) {
    if (!lazy[now]||tl==tr) return;
    mn[now<<]=mn[now<<|]=lazy[now<<]=lazy[now<<|]=lazy[now];
    lazy[now]=;
}
void dfs1(int now) {
    rep(i,,) fa[now][i]=fa[fa[now][i-]][i-];
    size[now]=;
    for (int i=ls[now];i;i=e[i].next) {
        if (e[i].y==fa[now][]) continue;
        dep[e[i].y]=dep[now]+;
        fa[e[i].y][]=now;
        dfs1(e[i].y);
        size[now]+=size[e[i].y];
    }
}
void dfs2(int now,int up) {
    pos[now]=++pos[]; bl[now]=up;
    int mx=;
    for (int i=ls[now];i;i=e[i].next) {
        if (e[i].y!=fa[now][]&&size[e[i].y]>size[mx]) mx=e[i].y;
    }
    if (!mx) return ;
    dfs2(mx,up);
    for (int i=ls[now];i;i=e[i].next) {
        if (e[i].y!=fa[now][]&&e[i].y!=mx) dfs2(e[i].y,e[i].y);
    }
}
void modify(int now,int tl,int tr,int l,int r,int v) {
    if (l>r||l==||r==) return ;
    push_down(now,tl,tr);
    if (tl==l&&tr==r) {
        mn[now]=lazy[now]=v;
        return ;
    }
    int mid=(tl+tr)>>;
    if (r<=mid) modify(now<<,tl,mid,l,r,v);
    else if (l>mid) modify(now<<|,mid+,tr,l,r,v);
    else {
        modify(now<<,tl,mid,l,mid,v);
        modify(now<<|,mid+,tr,mid+,r,v);
    }
    mn[now]=min(mn[now<<],mn[now<<|]);
}
int query(int now,int tl,int tr,int l,int r) {
    if (l>r||l==||r==) return INF;
    push_down(now,tl,tr);
    if (tl==l&&tr==r) return mn[now];
    int mid=(tl+tr)>>;
    if (r<=mid) return query(now<<,tl,mid,l,r);
    else if (l>mid) return query(now<<|,mid+,tr,l,r);
    else {
        int ql=query(now<<,tl,mid,l,mid),qr=query(now<<|,mid+,tr,mid+,r);
        return min(ql,qr);
    }
}
void opt2(int x,int y,int v) {
    while (bl[x]!=bl[y]) {
        if (dep[bl[x]]<dep[bl[y]]) swap(x,y);
        modify(,,n,pos[bl[x]],pos[x],v);
        x=fa[bl[x]][];
    }
    if (dep[x]>dep[y]) swap(x,y);
    modify(,,n,pos[x],pos[y],v);
}
int get_lca(int x,int y) {
    if (dep[x]<dep[y]) swap(x,y);
    drp(i,,) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    if (x==y) return x;
    drp(i,,) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][];
}
int get_son(int x,int y) {
    drp(i,,) if (dep[fa[x][i]]>dep[y]) x=fa[x][i];
    return x;
}
int main(void) {
    n=read(),m=read();
    rep(i,,n) {
        int x=read(),y=read();
        addEdge(x,y);
    }
    fill(mn,); dep[]=;
    dfs1(); dfs2(,);
    rep(i,,n) modify(,,n,pos[i],pos[i],read());
    int root=read();
    while (m--) {
        int opt=read();
        if (opt==) root=read();
        else if (opt==) {
            int x=read(),y=read(),v=read();
            opt2(x,y,v);
        } else {
            int x=read();
            if (x==root) printf("%d\n",query(,,n,,n));
            else if (get_lca(x,root)!=x) printf("%d\n",query(,,n,pos[x],pos[x]+size[x]-));
            else {
                int son=get_son(root,x),prt=INF;
                if (pos[son]>) prt=min(prt,query(,,n,,pos[son]-));
                if (pos[son]+size[son]<=n) prt=min(prt,query(,,n,pos[son]+size[son],n));
                printf("%d\n",prt);
            }
        }
    }
    return ;
}
           

繼續閱讀