玲珑学院OJ 1017 Don't You Want Me?【枚举+二分】

1017 - Don't You Want Me?

Time Limit:2s Memory Limit:64MByte

Submissions:271Solved:50

DESCRIPTION

Eris has a string s=s1s2...sns=s1s2...sn. Let xx and yy be two characters in ss, f(x,y)f(x,y) be the difference between the number of occurrences of xx in ss and the number of occurrences of yy in ss and B(s)B(s) be the maximum value of f(x,y)f(x,y) (i.e. B(s)=maxx,ysf(x,y)B(s)=maxx,y∈sf(x,y)).

Eric wants to remove at most mm characters of ss to make B(s)B(s) as small as possible.

INPUT
There are multiple test cases. The first line of input contains an integer TT, indicating the number of test cases. For each test case:The first line contains two integers nn and mm (2n105,1m<n)(2≤n≤105,1≤m<n) -- the length of the string and the number of removals allowed.The second contains an string ss consisting of lowercase English letters.
OUTPUT
For each test case, output an integer denoting the minimum value of B(s)B(s).
SAMPLE INPUT
3
8 1
aaabbaac
2 1
aa
5 2
aabbc
SAMPLE OUTPUT
3
0
0

题目大意:

我们可以最多删除m个字符,使得每个字符出现的次数中最大值和最小值的绝对值差尽可能的小,问最小是多少。


思路:


1、首先我们统计每个字符出现的次数,然后对其进行排序。


2、一开始觉得对排序之后的序列,让最大值尽可能的小就能够得到正解了,其实不然,一些情况需要我们对最小值进行增大才行,所以我们只单单考虑最大值减小是不够的。

那么我们考虑枚举最大值和最小值。

此时我们可以枚举一个最小值,然后去二分最大值,将不在最小值和最大值之内的字符全部删除即可。

过程维护需要进行的删除个数,如果总共需要删除的个数小于等于m个,那么对应我们可以继续减小最大值,否则增大最大值。

过程维护最小差值即可。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int vis[500];
int b[100050];
char a[100050];
int n,m;
int cnt;
int Slove(int mid,int di)
{
    int need=0;
    for(int i=0;i<cnt;i++)
    {
        if(b[i]>mid)
        {
            need+=b[i]-mid;
        }
        else if(b[i]<di)need+=b[i];
    }
    if(need<=m)return 1;
    else return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cnt=0;
        memset(vis,0,sizeof(vis));
        scanf("%d%d",&n,&m);
        scanf("%s",a);
        for(int i=0;i<n;i++)
        {
            vis[a[i]]++;
        }
        for(int i=0;i<n;i++)
        {
            if(vis[a[i]]>0)
            {
                b[cnt++]=vis[a[i]];
                vis[a[i]]=0;
            }
        }
        sort(b,b+cnt);
        int output=0x3f3f3f3f;
        for(int i=0;i<cnt;i++)
        {
            int l=b[i];
            int r=b[cnt-1];
            int ans=-1;
            while(r-l>=0)
            {
                int mid=(l+r)/2;
                if(Slove(mid,b[i])==1)
                {
                    r=mid-1;
                    ans=mid-b[i];
                }
                else l=mid+1;
            }
            if(ans==-1)continue;
            output=min(output,ans);
        }
        printf("%d\n",output);
    }
}


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值