一: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