这一道题就是一道签到题
这道题我们可以很快速的发现,若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;
}
这道题可以直接用优先队列做出来(不会点这里)
用两个优先队列,一个大根堆,一个小根堆。用大根堆去存大于分数线的值,用小根堆去存小于分数线的所有值。
#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;
}