zoukankan      html  css  js  c++  java
  • BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度

    Time Limit: 10 Sec  Memory Limit: 1280 MB
    Submit: 3127  Solved: 795
    [Submit][Status][Discuss]

    Description

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

    问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

    Input

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

    Output


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

    Sample Input

    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

    Sample Output

    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。

    HINT

     

    Source

    zhonghaoxi提供


    这么快A掉好高兴

    没有换根,不就是dfs剖分裸题嘛?

    加上换根后,发现换根后树形态不变,两点之间路径不变,并且有些子树也没变

    对于询问分类讨论

    x==rt 查询[1,n](注意这里要特判,一开始没有处理)

    x在rt的子树内,子树没有变

    x不在rt到原根的链上,子树没有变

    x在rt到原根的链上,(即x=lca(x,rt)),发现现在x的子树就是整棵树减去x往rt方向向下那个节点的子树,于是倍增求那个点然后整个dfs序就是分成两段了啊

    dfs的问题:没有必要出栈单独,最后一种情况就是[1,L[v]-1]和[R[v]+1,n]

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define lc o<<1
    #define rc o<<1|1
    #define m ((l+r)>>1)
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    const int N=1e5+5,INF=2147483647;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,Q,rt,w[N],fw[N],op,a,b,v;
    struct edge{
        int v,ne;
    }e[N<<1];
    int cnt,h[N];
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    int deep[N],fa[N][20],tid[N],top[N],tot,size[N],mx[N];
    int L[N],R[N];
    void dfs(int u){
        size[u]=1;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v==fa[u][0]) continue;
            fa[v][0]=u;deep[v]=deep[u]+1;
            dfs(v);
            size[u]+=size[v];
            if(size[v]>size[mx[u]]) mx[u]=v;
        }
    }
    void dfs(int u,int anc){
        if(!u) return;
        tid[u]=L[u]=++tot;
        top[u]=anc;
        for(int j=1;(1<<j)<=deep[u];j++)
            fa[u][j]=fa[fa[u][j-1]][j-1];
        dfs(mx[u],anc);
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].v!=fa[u][0]&&e[i].v!=mx[u]) dfs(e[i].v,e[i].v);
        R[u]=tot;
    }
    int lca(int x,int y){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            x=fa[top[x]][0];
        }
        if(deep[x]>deep[y]) swap(x,y);
        return x;
    }
    
    struct node{
        int mn,set;
    }t[N<<2];
    inline void merge(int o){
        t[o].mn=min(t[lc].mn,t[rc].mn);
    }
    inline void paint(int o,int v){
        t[o].mn=t[o].set=v;
    }
    inline void pushDown(int o){
        if(t[o].set){
            paint(lc,t[o].set);
            paint(rc,t[o].set);
            t[o].set=0;
        }
    }
    void build(int o,int l,int r){
        if(l==r) paint(o,w[l]);
        else{
            build(lson);
            build(rson);
            merge(o);
        }
    }
    void segCha(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr) paint(o,v);
        else{
            pushDown(o);
            if(ql<=m) segCha(lson,ql,qr,v);
            if(m<qr) segCha(rson,ql,qr,v);
            merge(o);
        }
    }
    int segQue(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return t[o].mn;
        else{
            pushDown(o);
            int mn=INF;
            if(ql<=m) mn=min(mn,segQue(lson,ql,qr));
            if(m<qr) mn=min(mn,segQue(rson,ql,qr));
            return mn;     
        }
    }
    
    void change(int x,int y,int v){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            segCha(1,1,n,tid[top[x]],tid[x],v);
            x=fa[top[x]][0];
        }
        if(tid[x]>tid[y]) swap(x,y);
        segCha(1,1,n,tid[x],tid[y],v);
    }
    
    int jump2anc(int x,int d){
        int bin=deep[x]-d;
        for(int j=0;j<=17;j++) 
            if((1<<j)&bin) x=fa[x][j];
        return x;
    }
    int query(int x){
        if(x==rt) return segQue(1,1,n,1,n);
        else if(L[rt]<=tid[x]&&tid[x]<=R[rt]) return segQue(1,1,n,L[x],R[x]);
        else{
            int p=lca(x,rt);
            if(x!=p) return segQue(1,1,n,L[x],R[x]);
            else{
                int v=jump2anc(rt,deep[x]+1);
                return min(segQue(1,1,n,R[v]+1,n),segQue(1,1,n,1,L[v]-1));
            }
        }
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();Q=read();
        for(int i=1;i<=n-1;i++) a=read(),b=read(),ins(a,b);
        for(int i=1;i<=n;i++) fw[i]=read();
        rt=read();
        dfs(rt);dfs(rt,rt);
        for(int i=1;i<=n;i++) w[tid[i]]=fw[i];//,printf("hi %d %d %d  %d %d
    ",i,tid[i],w[tid[i]],L[i],R[i]);
        build(1,1,n);
        
        while(Q--){
            op=read();
            if(op==1) rt=read();
            else if(op==3) printf("%d
    ",query(read()));
            else{
                a=read();b=read();v=read();
                change(a,b,v);
            }
        }
    }
  • 相关阅读:
    android ListView加载不同布局
    实例演示如何在spring4.2.2中集成hibernate5.0.2并创建sessionFactory
    【翻译】Ext JS最新技巧——2015-10-21
    Android Studio下使用NDK的流程
    Android Studio JNI javah遇到的问题
    题解报告:hdu 1062 Text Reverse
    题解报告:hdu 1039 Easier Done Than Said?
    ACM_逆序数(归并排序)
    hdu 1556 Color the ball(区间修改,单点查询)
    hdu 1754 I Hate It(线段树)
  • 原文地址:https://www.cnblogs.com/candy99/p/6250295.html
Copyright © 2011-2022 走看看