2020CSP-J普及组复赛(民间数据)题解

T1 优秀的拆分

这一道题就是一道签到题

这道题我们可以很快速的发现,若n为奇数(即n%2==1),则n必定无法拆分;若n为偶数,其实就只需要有以下操作:

1.先通过计算2的k次幂,找到第一个满足大于等于n的值
2.计算当n-k>=0时,输出k,随后将k = k/2 最后当n等于0,则输出即为其优秀拆分

还可以直接把2的次幂打出来,再枚举

代码
#include
#include
#include
#include
using namespace std;
const int M=1e5+5;
int a[105]={0,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608};
int main(){
	int n;
	scanf("%d",&n);
	if(n%2==1){
		printf("-1");
		return 0;
	}
	int ans[105],cnt=0;
	for(int i=23;i>=1;i--){
		if(a[i]<=n){
			n-=a[i];
			printf("%d ",a[i]);
			cnt++;
			ans[cnt]=a[i];
		}
	}
	return 0;
}


T2 直播获奖

方法一(不知道是否是正解)

这道题可以直接用优先队列做出来(不会点这里)

用两个优先队列,一个大根堆,一个小根堆。用大根堆去存大于分数线的值,用小根堆去存小于分数线的所有值。

代码
#include
#include
#include
#include
#include
#include
using namespace std;
const int M=1e5+5;
priority_queue<int, vector<int>, greater<int> > Q1;
priority_queue<int> Q2;
int a[M];
int main(){
	int n,w;
	scanf("%d %d",&n,&w);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		
	}
	int Old=1;
    Q1.push(a[1]);
	printf("%d ",a[1]);
	for(int i=2;i<=n;i++){
        int now=i*w/100;
        now=(1,now);
		if(a[i] > Q1.top()) {
            Q1.push(a[i]);
            int k = Q1.top();
            Q2.push(k);
            Q1.pop();
        }
        else {
            Q2.push(a[i]);
        }
        if(now>Old){
            Old=now;
            int k=Q2.top();
            Q2.pop();
            Q1.push(k);
        }
        printf("%d ",Q1.top());
	}
	return 0;
}

方法二

观察到数据范围里成绩在600以内,因此可以用桶排序。有600个桶,每个选手处,把他分数对应的桶里的个数++。然后从第600号桶倒序循环到1号桶,进行人数统计,输出 m a x ( 1 , ⌊ p × w % ⌋ ) max(1, ⌊p×w\%⌋) max(1,p×w%)人处的分数。时间复杂度为 O ( 600 n ) O(600n) O(600n)

代码
#include
#include
#include
#include
using namespace std;
int n, w, b[605];
int main(){
    cin >> n >> w;
    for (int i = 1; i <= n; i ++) {
        int v;
        cin >> v;
        b[v]++;
        int cnt = max(1, i * w / 100);
        int k = 600, sum = 0;
        while (k >= 0) {
            if (sum + b[k] < cnt) {
                sum += b[k];
                k --;
            }
            else{
                cout << k << " ";
                break;
            }
        }
    }
    return 0;
}


你可能感兴趣的:(比赛,c++)