C. Arthur and Table

链接

[https://codeforces.com/contest/557/problem/C]

题意

给你每个木棍的长度,以及移除每个木棍的代价
使得桌子稳定,最长的木棍必须大于剩下的一半

分析

这个数据范围,就是得暴力和前缀和还有一些技巧
枚举每一种长度,大于它的全部移除,
那么剩下的就尽可能地移除少量的木棍,而且移除可以移除的最小代价
复杂度2e7左右。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct str{
    int l,d;
}a[maxn];
int num[maxn];//长度为i的数量 
int prenum[maxn];//长度小于等于i的有多少个 
int s[maxn];// 第i个之前全部移除需要的代价 
int t[210];//当前代价为i的有多少个 
bool cmp(str x,str y){
    if(x.l==y.l) return x.d<y.d;
    return x.l<y.l;
}

int main(){
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n;
    while(cin>>n){
        memset(num,0,sizeof(num));
        memset(prenum,0,sizeof(prenum));
        memset(s,0,sizeof(s));
        memset(t,0,sizeof(t));
        for(int i=1;i<=n;i++)
        {
            cin>>a[i].l;
            num[a[i].l]++;
        }
        
        for(int i=1;i<=n;i++)
        cin>>a[i].d;
        
        sort(a+1,a+n+1,cmp);
         
         for(int i=1;i<=n;i++)
         s[i]=s[i-1]+a[i].d;
         
         for(int i=1;i<=100000;i++)
         prenum[i]=prenum[i-1]+num[i];
         int ans=1e9;
         
         for(int i=1;i<=100000;i++)
         {
            if(!num[i]) continue;
            int tem=prenum[i]-(2*num[i]-1);//该移除的个数 
            int cur=s[n]-s[prenum[i]];
            //cout<<i<<' '<<tem<<' '<<cur<<endl;
                for(int j=1;j<=200&&tem>0;j++)
                {
                    if(tem>=t[j]){
                        tem-=t[j];
                        cur+=t[j]*j;
                     }
                     else {
                        cur+=tem*j;
                        tem=0;
                     }
                 }
             ans=min(ans,cur);
             for(int j=prenum[i-1]+1;j<=prenum[i];j++)
             t[a[j].d]++;
            
         }
         cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mch5201314/p/10982289.html