zoukankan      html  css  js  c++  java
  • codeforces 982D Shark

    题意:

    给出一个数组,删除大于等于k的数字,使得其满足以下条件:

    1.剩余的连续的段,每一段的长度相等;

    2.在满足第一个条件的情况下,段数尽可能多;

    3.在满足前两个条件的情况下,k取最小的。

    求k。

    思路:

    一开始整个数组可以看成完整的一段,这是对应的k是最大的数字 + 1。

    用一个set sd维护删除的数字。

    从大到小枚举删除的数字,每次删除一个数字,都可以看成是删除一个长的段,然后添加两个小的段,在sd中找出这个数字的位置cur的前驱pre和后继sub,要删除的段就是前驱到后继这一段,然后新添加两段就是cur到pre 以及 sub到cur。把cur添加到删除数字的集合中。

    用一个map维护<线段长度,数量>来表示现在段数的情况,容易知道当map的size为1时,表明所有线段的长度相同,就可以更新答案了。

    更新答案的时候,首先考虑线段数量是否更多,再考虑k是否可以变小。

    假设当前删除的数字是tmp,那么是不是满足条件之后就直接把答案更新为tmp呢?

    不是,假设当前数字是x,比它小的第一个数字是y,显然y + 1这个数字也可以满足条件,而且y + 1 <= x是显然的,所以答案应该更新为y + 1。

    感谢mzjj教我!

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 #include <map>
     5 #include <set>
     6 using namespace std;
     7 typedef long long ll;
     8 typedef pair<int,int> pii;
     9 map<int,int> mmp;
    10 set<pii> s;
    11 set<int> sd;
    12 int main()
    13 {
    14     int n;
    15     scanf("%d",&n);
    16     for (int i = 1;i <= n;i++)
    17     {
    18         int x;
    19         scanf("%d",&x);
    20         s.insert(pii(x,i));
    21     }
    22     sd.insert(0);
    23     sd.insert(n+1);
    24     mmp[n]++;
    25     int ans = s.rbegin() -> first + 1;
    26     int cnt = 1;
    27     for (int i = 0;i < n - 1;i++)
    28     {
    29         auto it = s.rbegin();
    30         int cur = it -> second;
    31         s.erase(*it);
    32         int pre = *(--sd.lower_bound(cur));
    33         int sub = *(sd.upper_bound(cur));
    34         //printf("%d %d %d
    ",pre,sub,cur);
    35         if (sub-pre-1 > 0)
    36         {
    37             mmp[sub-pre-1]--;
    38             if (mmp[sub-pre-1] == 0)
    39             {
    40                 mmp.erase(sub-pre-1);
    41             }
    42         } 
    43         sd.insert(cur);
    44         if (cur-pre-1 > 0) mmp[cur-pre-1]++;
    45         if (sub-cur-1 > 0) mmp[sub-cur-1]++;
    46         if (mmp.size() == 1)
    47         {
    48             //int len = mmp.begin() -> first;
    49             int num = mmp.begin() -> second;
    50             //printf("%d *
    ",len);
    51             if (num >= cnt)
    52             {
    53                 cnt = num;
    54                 ans = s.rbegin() -> first + 1;
    55             }
    56         }
    57     }
    58     printf("%d",ans);
    59     return 0;
    60 }
  • 相关阅读:
    EOJ 2743 Stock Exchange
    POJ-3468 A Simple Problem with Integers
    EOJ-1104 bitmap
    【转】旋转卡壳——凸多边形间对踵点对(定义)
    Ring 3层枚举进程的四种方法
    XX-Net项目,免费浏览谷歌的伟大项目
    浅析Java中的内存机制
    Ubuntu下eclipse中安装Scala插件
    注入(5)---导入表注入(HookINT)
    Linux下MySQL导入文件出错ERROR 1290 (HY000)
  • 原文地址:https://www.cnblogs.com/kickit/p/9062168.html
Copyright © 2011-2022 走看看