第三周解题报告

一:Counting Kangaroos is Fun

 

题目链接:

http://codeforces.com/problemset/problem/372/A

题目大意:

一个数可以被比他大两倍以上的数包起来,小的数被隐藏,每个数只能被使用一次,求能看见的最少个数。

第一行输入n < 5 e 5,  之后输入n  每个数 s  < 1e5

 

    根据贪心思想  每个数刚好被大它两倍得数隐藏可隐藏的数最多,读进来的数首先肯定要用sort排序然后从中间分开  左边是可能会被隐藏的数,右边为用来将小的数包起来的大数。

如果直接用两层for循环暴力查找复杂度为(n^2)。1s内肯定跑不出来。

         要保证最后剩余的数尽量少,就要保证大的数尽可能都遮挡一个小数,用一个for从最大的数枚举,用一个指针来从小数中最大的往小数扫,如果这个数不能被当前的大数隐藏,那么之后的大数也不能将它隐藏,继续往左扫,当小数能被当前的大数隐藏后,数量减一,for进入下一个大数,指针继续接着往左扫。这样一来复杂度就变成O(n);

 

代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 
 9 int n;
10 int num[500000 + 5];
11 int p;
12 int cont;
13 int main()
14 {
15     scanf("%d", &n);
16     for(int i = 1; i <= n; i++)
17     {
18         scanf("%d", &num[i]);
19     }
20     cont = n;
21     sort(num + 1, num + n + 1);
22     p = n / 2;
23     for(int i = n; i >= (n + 1) / 2; i--)
24     {
25         while( p >= 1 && num[p] * 2 > num[i]) p--;
26         if(p > 0) 
27         {
28             cont--;
29             p--;
30         }
31     }
32     printf("%d\n", cont);
33     return 0;
34 }

 

二:New Year Ratings Change

 

题目链接:

http://codeforces.com/problemset/problem/379/C

 

题目大意:

第一行输入n 第二行输入n个数  要求输出数的和最下并且每个数都不同。

最后按原顺序输出改变后的数。

 

解题思路:

如果不考虑输出顺序,那么讲数据sort排序从小到大  如果这个数个前面的数相同,就将这个数加一,这样能保证最后的和尽可能小的同时每个数都不同,

但是题目要求是原来的顺序输出,所以考虑到用指针,再根据指针进行sort排序,这样能保证输出的时候顺序不变。

 

代码如下:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>

using namespace std;
int n, cont;
int num[300000 + 5];
int *pnum[300000 + 5];
bool cmp(int *x, int *y)
{
    if(*x < *y) return 1;
    else return 0;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n ; i++)
    {
        scanf("%d", &num[i]);
        pnum[i] = &num[i];
    }
    sort(pnum + 1, pnum + 1 + n, cmp);
    for(int i = 1; i <= n; i++)
    {
        cont++;
        cont = max(cont, *pnum[i]);
        *pnum[i] = cont;
    }
    for(int i = 1; i < n; i++)
        printf("%d ", num[i]);
    printf("%d", num[n]);
    return 0;
}

 

 

三:Complete the Word

 

题目链接:http://codeforces.com/problemset/problem/716/B

 

题目大意:

给定一个字符串 s < 5 e4  有大写字母和? 问是否能从其中找到一个长度为26的子区间使26个字母只出现一次,如果可以,将问号变成正确的字母。

 

解题思路:

 

长度只有5e4  可以枚举从第一个字母到n – 25个字母,每次截取26个长度,用数组计数每个字母是否只出现了一次,如果都符合,就将剩余的?填上没被计数的字母,确定了这个子区间后,区间外的?可用任意字母代替比如A最后输出改变后的字符串,如果没有符合的子区间,输出-1.

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 5e4;
10 char box[N + 5];
11 int n;
12 int str;
13 bool flag[N + 5];
14 int pas = -1;
15 int num[100];
16 int main()
17 {
18     memset(box, 0, sizeof(box));
19     scanf("%s", box);
20     str = strlen(box);
21     for(int i = 0; i <= str - 26; i++)
22     {
23         memset(num, 0, sizeof(num));
24         for(int j = i; j <= i + 25; j++)
25         {
26             if(box[j] != '?')
27                 num[box[j]]++;
28             if(num[box[j]] > 1) flag[i] = 1;
29         }
30         if(flag[i] == 0) 
31         {
32             pas = i;
33             break;
34         }
35     }
36     if(pas != -1)
37     {
38         for(int i = pas; i <= pas + 25; i++)
39         {
40             if(box[i] != '?')
41                 num[box[i]]++;
42             else 
43             {
44                 int j = 65;
45                 while(num[j] != 0)
46                 {
47                     j++;
48                 }
49                 box[i] = (char)j;
50                 num[j]++;
51             }
52         }
53         for(int i = 0; i < str; i++)
54         {
55             if(box[i] == '?')
56                 box[i] = 'A';
57         }
58         printf("%s\n", box);
59     }
60     else 
61         printf("-1\n");
62     return 0;
63 }
64     

 

posted @ 2016-11-04 19:57  ZZZZone  阅读(140)  评论(0编辑  收藏  举报