ABC143 F - Distinct Numbers(思维,决策单调性)

题意:

在这里插入图片描述

解法:

参考:https://blog.csdn.net/qq_39973668/article/details/102925705
容易想到只需要计算每种数出现的次数,不需要管数的大小.

将数抽象成若干个矩形,然后取数肯定是选出k列,每列取一其中一个.

当k固定时,设答案为x,那么一定能用填补法一定能填出k*x的矩形.

我们要做的就是对于固定的k,计算出满足条件的最大的x.

同时当k增加时,x是非递增的,是单调的,
利用单调性可以开一个指针维护这个x,然后整个过程复杂度就变为O(n).

code:

#include<bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
const int maxm=2e6+5;
int cnt[maxm];
int pre[maxm];
int suf[maxm];
int ans[maxm];
int a[maxm];
int n;
void solve(){
    
    
    cin>>n;
    for(int i=1;i<=n;i++){
    
    
        int x;cin>>x;
        a[x]++;//计算每种数的高度
    }
    for(int i=1;i<=n;i++){
    
    //计算每种高度的出现次数
        cnt[a[i]]++;
    }
    for(int i=n;i>=1;i--){
    
    //高度>=i的柱子数量,也可以看作第i层的格子数量
        cnt[i]=cnt[i+1]+cnt[i];
    }
    for(int i=1;i<=n;i++){
    
    //<=i层的格子数量和
        pre[i]=pre[i-1]+cnt[i];
    }
    int x=n;
    for(int k=1;k<=n;k++){
    
    
        while(x>=1&&pre[x]<k*x){
    
    //x是非递增的
            x--;
        }
        ans[k]=x;
    }
    for(int i=1;i<=n;i++){
    
    
        cout<<ans[i]<<endl;
    }
}
signed main(){
    
    
    ios::sync_with_stdio(0);
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/115217064