自己手撕WA 19
#include<iostream>
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
int a[200010];
int a1[200010];
int need[200010];
int number1;
int sum;
struct Node
{
int x;
int number;
bool friend operator <(Node xx,Node yy)
{
return xx.number<yy.number;
}
}t;
priority_queue<Node> q;
int main()
{
int n,k;
scanf("%d %d",&n,&k);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
a1[i]=x;
a[x]++;
}
for(int i=1;i<=200000;i++)
if(a[i]>1)
{
t.x=i;t.number=a[i];
//cout<<"x : "<<t.x<<endl;
//cout<<"number : "<<t.number<<endl;
sum+=a[i];
q.push(t);
}
if(sum>=2*k)
{
while(!q.empty())
{
t=q.top();
q.pop();
//cout<<t.x<<endl;
need[number1++]=t.x;
if(t.number/2!=0)
{
t.number=t.number/2;
q.push(t);
}
if(number1==k) break;
}
for(int i=0;i<number1;i++)
{
if(i==number1-1) printf("%d\n",need[i]);
else printf("%d ",need[i]);
}
}
else
{
for(int i=0;i<k;i++)
{
if(i==k-1) printf("%d\n",a1[i]);
else printf("%d ",a1[i]);
}
}
return 0;
}
自己造了些样列以为对了 当时自己对于为什么 /2解释不清楚觉得应该就能对,其实不然,当时以为把一份出现次数比较的多的分成两份再去排序比较,其实漏掉了很多种情况,因为不止分成两份,还可能分成3,4,5,....,n-1(不需要考虑n因为那个种情况随意k个数都是操作一次)所以问题变的复杂了,然后去看大神的题解,发现二分操作次数,找到最大的操作次数,然后根据每一个数字出现的次数分析这个数字可以被分成多少个部分,比如说:一个数出现了6次,而最大操作次数为2,则这个数可以被分成6/2=3份,相当与这个数可以被看成独立的三个数字。
正确代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5+10;
int a[N], n, k, x;
bool cmp(int x, int y)
{
return x > y;
}
bool ok(int m)
{
int ans = 0;
for(int i = 0; i < N; i ++) if(a[i])ans += a[i]/m;
return ans >= k;
}
int main()
{
cin >> n >> k;
for(int i = 1; i <= n; i ++)
{
cin >> x;
a[x]++;
}
int l = 1, r = n/k, MAX = 0;
while (l <= r)
{
int m = (l+r) >> 1;
if(ok(m))
{
MAX = max(MAX, m);
l = m + 1;
}
else r = m-1;
}
int ans = 0;
for(int i = 0; i < N; i ++)
{
for(int j = 0; j < a[i]/MAX; j ++)
{
if(ans == k) break;
printf("%d%c",i,ans==k-1?'\n':' ');
ans ++;
}
}
return 0;
}