codeforces 1077D

题目:https://codeforces.com/contest/1077/problem/D

题意:给你一个长度为n的串,你需要在里面找到出现次数最多的长度为k的子序列(子序列中元素可重复),求这个子序列

题解:方法一:二分最大次数,然后将排序后的数依次填进去。

   方法二:贪心,这个子序列出现的最大次数就是,将出现次数从大到小排序,从最大的开始找,找到第i个数可以使得第i个数的次数大于等于子序列出现的次数,并且前i个数出现次数的和除k大于最大出现的次数即可,最后子序列就直接一个个填数即可。

代码如下:

二分:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#define LL long long
#define debug(x) cout << "[" << x << "]" << endl
using namespace std;

const int mx = 2e5+10;
struct node {
    int a, num;
    bool operator < (const node& b) const {
        return num > b.num;
    }
};
vector<node> v;
int a[mx], vis[mx];
int n, k;

bool check(int mid) {
    int sum = 0;
    for (int i = 0; i < v.size(); i++) {
        sum += v[i].num/mid;
    }
    return sum >= k;
}

int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        vis[a[i]]++;
    }
    sort(a+1, a+1+n);
    int m = unique(a+1, a+n+1)-a-1;
    for (int i = 1; i <= m; i++) {
        v.push_back(node{a[i], vis[a[i]]});
    }
    sort(v.begin(), v.end());
    int l = 1, r = 1e9, ans = 0;
    while (l <= r) {
        int mid = (l+r)>>1;
        if (check(mid)) l = mid+1;
        else r = mid-1, ans = r;
    }
    for (int i = 0; i < v.size(); i++) {
        if (k == 0) break;
        int t = v[i].num/ans;
        while (t--) printf("%d ", v[i].a), k--;
    }
    return 0;
}
View Code

贪心:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;

int vis[maxn*2];
struct node {
    int cnt;
    int id;
} a[maxn];
bool cmp(node a,node b) {
    return a.cnt>b.cnt;
}
int main() {
    int n,k;
    int maxx=-1;
    scanf("%d%d",&n,&k);
    int x;
    for(int i=0; i<n; i++) {
        scanf("%d",&x);
        maxx=max(maxx,x);
        vis[x]++;
    }
    int t=0;
    for(int i=1; i<=maxx; i++) {
        if(vis[i]!=0) {
            a[t].cnt=vis[i];
            a[t].id=i;
            t++;
        }
    }
    /*****
    前面全部是去重和
    *****/
    sort(a,a+t,cmp);
    int sum=0,ans=0,id=0;
    for(int i=0;i<t;i++){
        sum+=a[i].cnt;
        if(ans<=a[i].cnt&&sum/k>ans){//第i大的数出现的次数大于最多次数,更新最多次数
            id=i;//记录最大到几
            ans=sum/k;//会有多少个这样的t串
        }
    }
    vector<int> vec;
    for(int i=0;i<=id;i++){
        int time=a[i].cnt/ans;//这个数可以被放的次数
        for(int j=0;j<time;j++){
            vec.push_back(a[i].id);
        }
    }
    for(int i=0;i<vec.size();i++){
        printf("%d ",vec[i]);
    }




}
View Code

猜你喜欢

转载自www.cnblogs.com/buerdepepeqi/p/9972719.html