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\n",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 *\n",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 }

 

posted @ 2018-05-19 23:54  qrfkickit  阅读(638)  评论(2编辑  收藏  举报