• ZCMU--5087: 宠物


    Description

    现在有一个宠物收养所,提供两种服务,可以将被主人遗弃的宠物放到收养所里,如果有人希望可以领养宠物的话,他也可以来收养所领养被别人遗弃的宠物。

           为了方便领养者领养宠物,所以这里给每个宠物和领养者进行了评估,记为特征值(当然任何两只宠物的特征值都是不同的,任何两个人的特征值也是不同的),那么对于特征值越相近的宠物和领养者,他们更容易相处,也会更加开心。

           收养所总是会有两种情况发生:宠物过多或者领养者过多。

    1.       当宠物过多时,若有一个领养者到来,这个领养者的特征值为x,那么他将会领养现在收养所的所有宠物中特征值最接近x的一只宠物,如果有两只宠物满足 x-a = b-x (ax),那么这个领养者会领养特征值为a的宠物

    2.       当领养者过多时,那么领养者会在收养所中登记,当来到一只宠物时,设它的特征值为x,那么会领养它的领养者就是特征值最接近x的人,如果有两个领养者满足x-a = b-x (ax),那么这只宠物会被特征值为a的领养者领养。

    当一个特征值为x的领养者领养了一只特征值为y的宠物以后,他的不开心程度为abs(x-y)。

    现在告诉你一段时间中,领养者和被遗弃的宠物来到收养所的顺序,希望你计算所有领养了宠物的领养者的不开心程度的总和,当然在这段时间开始前,收养所里没有任何宠物也没有登记任何领养者。

    Input

    数据第一个行包含一个正整数n,表示这段时间中来到收养所的宠物和领养者的总数。

    接下来n行表示按顺序到来的领养者或者宠物的情况。每行两个整数 x,y ,其中 x=0 表示这次到来的是一只宠物,x=1表示这次到来的是一个领养者,y表示的是这次来到的宠物或领养者的特征值(保证同一时间内收养所中不会有超过10000只宠物,也不会登记超过10000个领养者)

    Output

    输出包含一个整数表示这段时间中所有收养了宠物的领养者的不满意程度的总和,因为这个答案比较大,所以对998244353 取模。

    Sample Input

    5
    0  2
    0  4
    1  3
    1  2
    1  5

    Sample Output

    3

    HINT

    第一个领养者会领养特征值为2的宠物

    第二个领养者会领养特征值为4的宠物

    第三个领养者没有宠物可以领养

    总的不满意程度为abs(3-2)+abs(2-4)=3

     40%的数据保证: 1≤n≤800

    100%的数据保证:1≤n≤80000,a<=2^31-1

    解析:利用vector二分插入,二分查找然后按题意比较即可,注意下边界😢

    开两个vector数组a,b,一个宠物一个领养者

    1.如果输入是宠物时,先看b中有没有人,没有人的话就偷偷用lower_bound( begin,end,num)👀,查找第一个大于或等于num的数字,找到返回该数字的地址,实现宠物插入a数组

    2.有领养者的话二分查找第一个大于等于v的位置z,因为前后是b[z-1]和b[z],避免z-1越界,分2种情况,如果是第一个位置,那肯定选他,其他情况需要比较b[z-1]和b[z]哪个更接近,选了之后再在数组中删除即可。

    3.输入是人的话,相反同理

    1. #include
    2. #include
    3. #include
    4. const int mod=998244353;
    5. using namespace std;
    6. vector<int> a,b;
    7. int main()
    8. {
    9. int n,y,s=0,z,m,k,v;
    10. scanf("%d",&n);
    11. while(n--){
    12. scanf("%d%d",&k,&v);//k来判断是宠物还是人,v是特征值
    13. if(k==0){
    14. if(b.size()>0){//如果有人
    15. z=0;y=b.size()-1;
    16. while(z
    17. m=(z+y)>>1;
    18. if(b[m]>=v) y=m;
    19. else z=m+1;
    20. }
    21. //a[z]是第一个大于等于v的位置
    22. if(z==0) s=(s+abs(v-b[z]))%mod,b.erase(b.begin());//第一个位置,肯定是他无疑
    23. else if(abs(v-b[z-1])<=abs(b[z]-v)) s=(s+abs(v-b[z-1]))%mod,b.erase(b.begin()+z-1);//前面一个更接近
    24. else if(abs(v-b[z-1])>abs(b[z]-v)) s=(s+abs(v-b[z]))%mod,b.erase(b.begin()+z);//后面更接近
    25. }else a.insert(lower_bound(a.begin(),a.end(),v),v);//没人,存进宠物
    26. }else{
    27. //跟上面反一下,同理
    28. if(a.size()>0){ //如果有宠物
    29. z=0;y=a.size()-1;
    30. while(z
    31. m=(z+y)>>1;
    32. if(a[m]>=v) y=m;
    33. else z=m+1;
    34. }
    35. if(z==0) s=(s+abs(v-a[z]))%mod,a.erase(a.begin());
    36. else if(abs(v-a[z-1])<=abs(a[z]-v)) s=(s+abs(v-a[z-1]))%mod,a.erase(a.begin()+z-1);
    37. else if(abs(v-a[z-1])>abs(a[z]-v)) s=(s+abs(v-a[z]))%mod,a.erase(a.begin()+z);
    38. }else b.insert(lower_bound(b.begin(),b.end(),v),v);//没宠物存人
    39. }
    40. }
    41. printf("%d\n",s);
    42. return 0;
    43. }

  • 相关阅读:
    在raspberry上装ubuntu
    Linux起源
    VTK:2D直方图的用法与编程实例
    什么是GPT与MBR
    贪心算法实现背包问题(背包可拆分)
    微信小程序navigateTo进入页面后返回原来的页面需要携带数据回来
    【LeetCode每日一题】——1379.找出克隆二叉树中的相同节点
    基于WPF重复造轮子,写一款数据库文档管理工具(一)
    导入自己的jacoco exec文件到IDEA并进行展示
    Qt 编译纯c的C99的项目, error: undefined reference to `f()‘
  • 原文地址:https://blog.csdn.net/qq_63739337/article/details/126337818