1030 完美数列 (25分)
题目
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。
输入格式
输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线 _(代表空格)组成。题目保证 2 个字符串均非空。
输出格式
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。
输入样例:
7_This_is_a_test
_hs_s_a_es
输出样例:
7TI
解析
先将数列排序然后从两头开始找,因为排过序了,假设某数列M>mp,那么要满足条件,要么最大值往前来一个,要么最小值往后去一个可能会疑惑排序了还对嘛?实际找的最大值最小值,排序之后两最值之间的数就是最多的数
注意题目也不是说连续的最大子序列,而是从中选择尽可能多的数呐
答案
最小值从0开始,最大值从n-1开始,不满足条件并且i < j的时候就将j往前移动一个
满足条件的时候 j - i + 1,即为所求最大值
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
long long int a[100001];
int main(){
long long int n,m;
int now = 0,max = 0;
cin >>n >>m;
for(int i = 0 ; i < n ; i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
for(int i = 0 ; i < n ; i ++){
int j = n - 1;
while(a[j] > a[i] * m ){
j --;
}
now = j - i + 1 ;
if(max < now){
max = now;
}
}
cout << max;
}
遗憾的是,测试点4超时了

虽然没用cin输入数列,任然超时,其中最耗时的无疑就是for与里边的while了
需要想办法优化一下
Emmmm~最终我选择在while循环前判断一下这个数是否和上一个数相等,如果相等那就不用算了一定是上一个数结果最大
于是加了这一句
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
long long int a[100001];
int main(){
long long int n,m;
int now = 0,max = 0;
cin >>n >>m;
for(int i = 0 ; i < n ; i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
int j = 0, k = n-1;
for(int i = 0 ; i < n ; i ++){
if(a[i] == a[i-1]) continue;//这一句
int j = n - 1;
while(a[j] > a[i] * m ){
j --;
}
now = j - i + 1 ;
if(max < now){
max = now;
}
}
cout << max;
}
嘻嘻嘻,过了!😁

还能优化呐,根据当前最大个数max,那么下一次就直接从i + max开始判断啦,它以前再怎么也不会比max大
现在的时间呢

amazing!代码在这
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int a[100001];
int main(){
long long int n,m;
int now = 0,max = 0;
cin >> n >> m;
for(int i = 0 ; i < n ; i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
for(int i = 0 ; i < n ; i ++){
if(a[i] == a[i-1]) continue;
int j = i + max ;
while(j < n && a[j] <= a[i] * m){ // 这里一定要把 j < n 放在前面
j ++;
}
now = j - i;
if(now>max)
max=now;
}
cout << max;
}

浙公网安备 33010602011771号