zoukankan      html  css  js  c++  java
  • HDU 4366 Successor (dfs序列+分块)

    题目

    Problem Description
    Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty and ability.Some times Sean will fire one staff.Then one of the fired man’s Subordinates will replace him whose ability is higher than him and has the highest loyalty for company.Sean want to know who will replace the fired man.

    题解

    给你一个棵树,每棵树有两个属性,忠诚度和能力值,给你一个点,在他的子孙节点中找到比他能力值强且最忠诚的一个,顶替他的位置,输出编号。好像一个二维偏序?假设我们已经有了这个点的子孙区间,我们该如何得到这个值,考虑一下分块,朴素的扫法就是两个条件去判断,过程中去极值。那么我们想一下如何维护大段,根据二维偏序的做法,我们只需要在排好序的分块数组里面二分出这个点的位置,然后扫一遍剩余的点,取最大值就可以了,那么这个东西我们在建立分块的时候就可以(O(N))预处理出来,所以我们只需要在每个大段里面二分位置就可以了,左右区间朴素扫。子孙区间的话,维护个dfs序就好了。ps:lower_bound和upper_bound是走闭右开,R!N!M!

    Code

    #include<set>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    using namespace std;
    const int maxn=50000+10;
    const int MOD=1e9+7;
    const int INF=0x3f3f3f3f;
    struct node{
        int name, loyalty, ability;
        bool operator < (const node &x) const{
            return ability < x.ability;
        }
    }p[maxn];
    int L[maxn],R[maxn];
    int loyalty[maxn], ability[maxn];
    int in[maxn],out[maxn];    //在dfs序列中的位置1-id
    int belong[maxn], id;
    int head[maxn], tot;
    
    int st[maxn],to[maxn],nt[maxn],topt;
    void init(){
        topt=id=0;
        memset(st,0,sizeof(st));
    }
    
    void add_edge (int u,int v) {
        to[++topt]=v;
        nt[topt]=st[u];
        st[u]=topt;
    }
    void dfs(int u){
        in[u]=++id;
        p[id].ability=ability[u],p[id].loyalty=loyalty[u],p[id].name=u;
        int now=st[u];
        while (now) {
            dfs (to[now]);
            now=nt[now];
        }
        out[u]=id;
    }
    int MaxLoy[maxn];    
    int n,m,block,sz;
    int solve(int x){
        int l=belong[in[x]], r=belong[out[x]];
        int a,b;
        int MaxLoyalty=-1, ans=-1;
    
        a=L[l],b=R[l];
        for(int i=a;i<=b;i++) {
            if(in[p[i].name]>in[x]&&out[p[i].name]<=out[x]) {
                if(p[i].loyalty>MaxLoyalty&&p[i].ability>ability[x]) {
                    MaxLoyalty=p[i].loyalty;
                    ans=p[i].name;
                }
            }
        }
        a=l+1,b=r-1;
        node c;
        c.ability=ability[x];
        for(int i=a;i<=b; i++){
            int s=block*(i-1)+1,e=s+block;
            int pos=upper_bound(p+s,p+e,c)-p;
            if(pos >= e) continue;
            int tmp=MaxLoy[pos];
            if(p[tmp].loyalty>MaxLoyalty){
                MaxLoyalty=p[tmp].loyalty;
                ans = p[tmp].name;
            }
        }
    
        a=L[r],b=R[r];
        for(int i=a;i<=b;i++){
            if(in[p[i].name]>in[x]&&out[p[i].name]<=out[x]){
                if(p[i].loyalty>MaxLoyalty&&p[i].ability>ability[x]){
                    MaxLoyalty=p[i].loyalty;
                    ans=p[i].name;
                }
            }
        }
        return ans;
    }
    
    void build () {
        block=sqrt (id);
        int num=id/block; if (id%block) num++;
        for (int i=1;i<=num;i++)  L[i]=(i-1)*block+1,R[i]=i*block;
        R[num]=id;
        for (int i=1;i<=id;i++) belong[i]=(i-1)/block+1;
        for (int i=1;i<=num;i++) {
            int s=L[i],e=min (R[i]+1,id);
            sort (p+s,p+e);
            int Max=-1,pos;
            for (int j=e-1;j>=s;j--) {
                if (Max<p[j].loyalty) {
                    Max=p[j].loyalty;
                    pos=j;
                }
                MaxLoy[j]=pos;
            }
        }
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        while(T--) {
            init();
            int a;
            scanf("%d%d", &n, &m);
            ability[0] = -1, loyalty[0] = -1;
            for(int i = 1; i <= n - 1; i++){
                scanf("%d%d%d", &a, &loyalty[i], &ability[i]);
                add_edge(a, i);
            }
            dfs(0);
            build ();
            while(m--) {
                scanf("%d", &a);
                printf("%d
    ", solve(a));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【Vue原理】Compile
    vue v-cloak 的作用和用法
    vue中template的作用及使用
    Vue-router 嵌套路由
    Vue keep-alive实践总结
    Vuex入门(2)—— state,mapState,...mapState对象展开符详解
    mysql允许外部连接设置
    Swagger入门教程
    牛客枚举题---铺地毯
    牛客区间求和、枚举、贪心题---数学考试
  • 原文地址:https://www.cnblogs.com/hhlya/p/14082251.html
Copyright © 2011-2022 走看看