• HDU7068:Dota2 Pro Circuit——题解


    https://acm.hdu.edu.cn/showproblem.php?pid=7068

    第 $i$ 个人初始得分为 $a_i$ ,每个人还可以不重复地取序列b中的一个数,最后按照分数从大到小排名。求每个人最好/最坏情况的排名。

    撒,细数我的罪恶(

    题目看错$n$次,还一直坚信二分能够极限卡过去。(

    (u1s1看数据范围内说最多8组$n=5000$我还以为真能卡过去结果我就SB了)

    最开始不难想到排名可以二分,检验的复杂度是$O(n)$的(贪心,为了维持排名我们需要至少一定数量的人比我们分高/低,显然初始得分越高/低的人越容易达成条件,而对于这些人,我们分配他们b中的大/小数,并且初始分越大的给的b越小即可。)

    此时复杂度还过不去,但是跑几组数据发现如果我们从大到小对初始得分排序的话可以发现最好/最坏情况是单调不增的(想想也是,我真傻,真的,在这破地方卡了2h),因此最终复杂度为$O(n^2)$

    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=5005;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct men{
        int w,i;
    }a[N];
    int b[N];
    bool cmp(men x, men y){
        return x.w>y.w;
    }
    int l[N],r[N],n;
    bool check1(int x,int i){
        if(x==1)return 1;
        int cnt=x-1;
        for(int j=1;j<=n;j++){
            if(i!=j){
                if(a[j].w+b[cnt--]<=a[i].w+b[n])return 0;
                if(cnt<1)break;
            }
        }
        return 1;
    }
    bool check2(int x,int i){
        if(x==n)return 1;
        int cnt=x+1;
        for(int j=n;j>=1;j--){
            if(i!=j){
                if(a[j].w+b[cnt++]>a[i].w+b[1])return 0;
                if(cnt>n)break;
            }
        }
        return 1;
    }
    int main(){
        int T=read();
        while(T--){
            n=read();
            for(int i=1;i<=n;i++){
                a[i].w=read();a[i].i=i;
            }
            for(int i=1;i<=n;i++){
                b[i]=read();
            }
            sort(a+1,a+n+1,cmp);
            int L=1,R=1;
            for(int i=1;i<=n;i++){
                while(R!=n&&check1(R+1,i))R++;
                while(L!=n&&!check2(L,i))L++;
                l[a[i].i]=L,r[a[i].i]=R;
            }
            for(int i=1;i<=n;i++){
                printf("%d %d
    ",l[i],r[i]);
            }
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    【Git】时光机命令—Git命令
    【Vue.js】vue引入组件报错:该组件未注册?
    【CSS】flex布局初认识
    【Vue.js】基于vue的实时搜索,在结果中高亮显示关键词
    MyBatis介绍并解决jdbc编程的问题
    MyBatis中 #{} 和 ${}的区别
    Mybatis执行操作时控制台日志中显示sql语句
    Mybatis中常见操作(基本操作+动态sql+sql片段+关联映射(resultMap))
    Spring配置初始化和销毁的方法
    平时工作常用linux命令总结
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/15153520.html
Copyright © 2020-2023  润新知