1. 程式人生 > >Codeforces Round #521 (Div. 3) D

Codeforces Round #521 (Div. 3) D

自己手撕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;
}