其他分享
首页 > 其他分享> > LevOJ P1719 Let's play a game!

LevOJ P1719 Let's play a game!

作者:互联网

P1719 Let's play a game!

题目描述

现有一包含n 个数的序列A1,A2,A3,...,An,给定一个定值k.

每次我们可以选择数列中一个下标为 2 的次幂的元素(如A1​,A2​,A4​,A8​...) 将其删除出数列(删除后,其后的所有元素会自动前移一格)。

问最少进行多少次操作,能将序列中所有值为k 的元素删除?

输入描述

第一行两个整数n,k

第二行nn 个整数,A1​,A2​,...,An​.

输出描述

第一行一个整数,为最少操作次数。

样例输入 1

5 2
1 2 4 2 5

样例输出 1

2

样例输入 2

5 2
1 2 2 2 2

样例输出 2

4

样例解释

对于样例11,依次删除A4​,A2​,即可。

对于样例22,连续删除4 次A2​,即可。

数据规模与约定

1≤n≤3×10^5。

  贪心做法,记录下每个指定值到自己前面的那个2的次方的距离,若在2的次方位置上,则可以直接删除,就是操作次数加1。

  不在2的次方上的话,有2种情况,第一种,已经进行删除的操作数,大于删除该数所需的操作数,直接操作数加1即可,也就是直接删掉。怎么理解这种情况呢,我们可以这样想,当前面删除时,后面的数会向前移,因为要删除的操作数,大于删除该数所需的操作数,那么正好当该数移动到2的次方位置上时,我们对它进行删除。

  第二种情况,已经进行删除的操作数,小于删除该数所需的操作数。我们取这个数所需的操作数。这个可以这样理解,当前面的数删除完成时,这个数已经快到能被删除的地方,那么再加上几次操作即可把这个数也删掉,这两次操作的数量加起来也就是要删除的这个数的操作数。

 1 #include <iostream>
 2 #include <cmath>
 3 using namespace std;
 4 #define N 300004
 5 int d[N];
 6 int distance(int n);
 7 int main()
 8 {
 9     //把每个要删除的数字的位置记录下来
10     //并且计算出他们到自己前面的2的次方的距离
11     //找到距离非0的位置,看前面有几个距离为0,若数量大于自己的距离,直接删除,若小于,则要取最大
12     int n, k, j = 0, result = 0, t;
13     cin >> n >> k;
14     for (int i = 0; i < n; i++)
15     {
16         cin >> t;
17         if (t == k)
18             d[j++] = distance(i + 1); //记录每个值到最近的2的次方的距离
19     }
20     for (int i = 0; i < j; i++) //从左到右扫描指定值
21     {
22         if (!d[i] || d[i] < result)
23             result++;
24         else
25             result = max(result, d[i]);
26     }
27     cout << result << endl;
28 }
29 int distance(int n)
30 {
31     for (int i = 0; i < n; i++)
32     {
33         if (pow(2, i) == n)
34             return 0;
35         else if (pow(2, i) > n)
36             return n - pow(2, i - 1) + 1;
37     }
38 }

 

标签:play,删除,int,样例,操作数,Let,result,次方,P1719
来源: https://www.cnblogs.com/hh22/p/16295550.html