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;
    }
    
  • 相关阅读:
    类变量、绑定方法、静态方法和类方法
    面向对象练习及补充
    2、error:file /usr/bin/ ** mysql-client-5.6.39-1.el7.x86_64
    15、Linux 磁盘映射DM
    14、echo “$JAVA_HOME/bin” >>/etc/profile 转义
    typora文件导出word
    1、Rocketmq centos7下安装及使用
    13、hostname及hostnamectl区别
    1、MySql集群
    Hadoop安装
  • 原文地址:https://www.cnblogs.com/hhlya/p/14082251.html
Copyright © 2011-2022 走看看