题目链接:https://vjudge.net/contest/280956#problem/D
大意:从长度为n的字符串中剪切长度为k的字符串序列,问能够剪切出最大次数的字符串时,结果是什么?
方法1:二分中间次数,WA了很多次,搞了差不多一天,晚上搞懂的原因。二分思路是:二分中间次数,确定最大值。先把每个数字的出现次数记录下来,确定最大值后遍历能够满足最大次数的数字,输出k个即可(WA了很多次)。注意二分整型数字的模板,参考这个:https://blog.csdn.net/fighting_yifeng/article/details/87877440
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int n,k,cur,top;
struct node
{
int num;
int ord;
} p[maxn];
bool vis[maxn];
bool cmp(node a,node b)
{
if(a.num != b.num)
return a.num > b.num;
return a.ord > b.ord;
}
bool judge(int x)
{
int cnt = 0;
for(int i = 0; p[i].num > 0; ++i)
cnt += p[i].num/x;
// printf("次数::%d::出现的字母%d\n",x,cnt);
if(cnt >= k)
return true;
else
return false;
}
int finds()
{
int l = 1,r = n,m,ans;
while( l <= r)
{
m = (l + r) >> 1;
if(judge(m))
{
ans = m;
l = m + 1;
}
else
r = m - 1;
}
return ans;
}
int main()
{
memset(p,0,sizeof(p));
for(int i = 0; i < maxn; ++i)
p[i].ord = i;
scanf("%d%d",&n,&k);
for(int i = 0; i < n; ++i)
{
scanf("%d",&cur);
p[cur].num++;
}
sort( p ,p + maxn,cmp);
int cnt = finds();
//printf("调试点%d\n",cnt);
/**for(int i = 0;i < n; ++i)
printf("%d %d\n",p[i].num,p[i].ord);**/
for(int i = 0; p[i].num >= cnt; ++i)
{
for(int j = 0; j < p[i].num/cnt; ++j)
{
printf("%d ",p[i].ord);
k--;
if(k == 0)
break;
}
if(k == 0)
break;
}
printf("\n");
return 0;
}
方法2:优先队列法,参考链接:https://blog.csdn.net/Amovement/article/details/84170385
利用优先队列将每个数字的次数等信息存储后,每次选取的数字应当是原始出现次数除于在k个数列中出现的次数就是每个数字的最大操作数。每次pop出这个次数最大的值,pop k次后答案出现
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
struct node
{
int ord;
int num;
int time;
bool operator < (const node & b)const
{
return num/time < b.num/b.time;
}
} p[maxn];
priority_queue<node>prio;
int num[maxn],n,k,cur,top = 0;
int main()
{
memset(num,0,sizeof(num));
scanf("%d%d",&n,&k);
for(int i = 0; i < n; ++i)
{
scanf("%d",&cur);
num[cur]++;
}
for(int i = 1; i < maxn; ++i)
if(num[i] > 0)
{
p[top].ord = i;
p[top].num = num[i];
p[top].time = 1;
prio.push(p[top++]);
}
vector<int>vec;
node nex;
while(vec.size() < k)
{
nex = prio.top();
prio.pop();
vec.push_back(nex.ord);
nex.time++;
prio.push(nex);
}
bool temp = 0;
while(vec.size() > 0)
{
if(temp)
printf(" ");
printf("%d",vec.back());
vec.pop_back();
if(!temp)
temp = 1;
}
return 0;
}