zoukankan      html  css  js  c++  java
  • BZOJ 3083 遥远的国度 树链剖分+脑子

    唉。。又调了半天QWQ。。为何读入挂了。。。。。莫非读入是反着的????据ywy学长所言如是。。。OvO震惊


    这啥骚题啊、、、还要换根、、、不过清明讲过、、、(然鹅我现在才做、、、

    先随便选个点(比如选1) 树剖板子一样搞一搞

    1操作 就直接改root变量的值

    2操作 线段树上改 换根不影响。。

    3操作 分成三种情况 :

      1.rt = u 整个树的min就是ans

      2. lca(rt,u) != u 求u子树的min就好了 换根不影响

      3. lca(rt,u) = u 找一下rt在u的子树里,求这个子树的补集的min就好了

        比如rt在以v为根的u的子树中,那么如果dfn [ v ] > 1 先求 1到dfn  [ v ] - 1的 min , (如果dfn [ v ]+sz[ v ] <= n)  就再求一下 dfn[v]+sz[v] 到 n 的min

    #include<cstdio>
    #include<iostream>
    #define R register int
    #define ls (tr<<1)
    #define rs (tr<<1|1)
    using namespace std;
    const int M=100010,Inf=0x7fffffff;
    inline int g() {
        R ret=0; register char ch; while(!isdigit(ch=getchar()));
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret;
    }
    int n,m,cnt,num,rt;
    int vr[M<<1],nxt[M<<1],fir[M],w[M],top[M],son[M],pre[M],sz[M],d[M],dfn[M],rw[M];
    int mn[M<<2],tg[M<<2];
    inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    inline void dfs(int u) { sz[u]=1; R mx=0;
        for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
            if(d[v]) continue; d[v]=d[u]+1,pre[v]=u; dfs(v);
            sz[u]+=sz[v]; if(sz[v]>mx) son[u]=v,mx=sz[v];
        }
    }
    inline void dfs2(int u,int tp) { dfn[u]=++num,rw[num]=u,top[u]=tp;
        if(son[u]) dfs2(son[u],tp);
        for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
            if(v!=son[u]&&v!=pre[u]) dfs2(v,v);
        }
    } 
    inline void build(int tr,int l,int r) {
        if(l==r) {mn[tr]=w[rw[l]]; return ;} R md=l+r>>1;
        build(ls,l,md),build(rs,md+1,r); mn[tr]=min(mn[ls],mn[rs]);
    }
    inline void spread(int tr) { if(tg[tr])
        tg[ls]=tg[tr],mn[ls]=tg[tr],
        tg[rs]=tg[tr],mn[rs]=tg[tr],tg[tr]=0;
    }
    inline void update(int tr,int l,int r,int LL,int RR,int inc) {
        if(LL<=l&&r<=RR) {mn[tr]=inc; tg[tr]=inc; return ;} spread(tr); R md=l+r>>1;
        if(LL<=md) update(ls,l,md,LL,RR,inc); if(RR>md) update(rs,md+1,r,LL,RR,inc);
        mn[tr]=min(mn[ls],mn[rs]);
    }
    inline int query(int tr,int l,int r,int LL,int RR) {
        if(LL<=l&&r<=RR) return mn[tr]; spread(tr); R md=l+r>>1,ret=Inf;
        if(LL<=md) ret=min(ret,query(ls,l,md,LL,RR)); if(RR>md) ret=min(ret,query(rs,md+1,r,LL,RR));
        return ret;
    }
    inline int lca(int u,int v) { 
        while(top[u]!=top[v]) {
            if(d[top[u]]<d[top[v]]) swap(u,v); u=pre[top[u]];
        } return d[u]>d[v]?v:u;
    }
    inline void change(int u,int v,int inc) {
        while(top[u]!=top[v]) {
            if(d[top[u]]<d[top[v]]) swap(u,v); 
            update(1,1,n,dfn[top[u]],dfn[u],inc);
            u=pre[top[u]];
        } if(dfn[u]>dfn[v]) swap(u,v); 
        update(1,1,n,dfn[u],dfn[v],inc);
    }
    inline int getmn(int u) { R v,ret=Inf;
        if(u==rt) return mn[1];
        R l=lca(u,rt);
        if(l!=u) return query(1,1,n,dfn[u],dfn[u]+sz[u]-1);
        else for(R i=fir[u];i;i=nxt[i]) if(lca(vr[i],rt)==vr[i]) {v=vr[i]; break;}
        if(dfn[v]>1) ret=min(ret,query(1,1,n,1,dfn[v]-1));
        if(dfn[v]+sz[v]<=n) ret=min(ret,query(1,1,n,dfn[v]+sz[v],n)); return ret;
    }
    signed main() {
        n=g(),m=g();
        for(R i=1,u,v;i<n;++i) u=g(),v=g(),add(u,v),add(v,u);
        for(R i=1;i<=n;++i) w[i]=g(); d[1]=1; rt=g(); dfs(1); dfs2(1,1);
        build(1,1,n);
        for(R i=1;i<=m;++i) {
            R k=g(),u=g(),v,inc;
            if(k==1) rt=u;
            else if(k==2) //change(u,g(),g());
            v=g(),inc=g(),change(u,v,inc);
            else if(k==3) printf("%d
    ",getmn(u));
        }
    }

    2019.04.22

  • 相关阅读:
    Facebook发布神经蛋分离法,可从嘈杂环境中提取音视频
    前线观察 | AWS re:Invent 2018见闻实录
    SSO
    8-5 Navicat工具与pymysql模块
    saltstack
    nginx 集群介绍
    Docker 持久化存储
    Docker 多机网络
    《深入理解JAVA虚拟机》笔记1
    jquery 学习日记之选择器
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10749599.html
Copyright © 2011-2022 走看看