您的位置:首页 > 其它

557C - Arthur and Table (前缀和)

2015-07-26 13:35 211 查看
如果选择L为最后的最长长度,那么大于L的桌腿必须全去除。然后假如此时剩下M条桌腿,长度L的桌腿有num[L]条,如果tmp=num[L]*2-1-M<=0就不需要再去除,如果tmp>0,就需要在小于L的腿中选择tmp条花费最小的桌腿。

首先把桌腿按长度排序然后预处理前缀和,这样后可以O(1)得到大于L的桌腿的总代价。

然后因为代价的最大值才200,那么维护小于L的每种代价桌腿的数量,按照计数排序的方法选择桌腿去除,再维护这个数量。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <algorithm>
int N;
struct node{
    int l,d;
}G[100005];
int num[100005];
int c[100005];
int n[100005];
int D[205];
bool cmp(node a,node b){
    if(a.l==b.l) return a.d<b.d;
    return a.l<b.l;
}

int main(){
    scanf("%d",&N);
    for(int i=0;i<N;i++){
        scanf("%d",&G[i].l);
        num[G[i].l]++;
    }
    for(int i=0;i<N;i++){
        scanf("%d",&G[i].d);
    }
    sort(G,G+N,cmp);
    c[0]=G[0].d;
    for(int i=1;i<N;i++){
        c[i]=c[i-1]+G[i].d;
    }
    n[0]=0;
    for(int i=1;i<=100000;i++){
        n[i]=n[i-1]+num[i];
    }
    int res=100000000;
    for(int i=1;i<=100000;i++){
        if(!num[i]) continue;
        int cur=c[N-1]-c[n[i]-1];
        int tmp=n[i]-(num[i]*2-1);
        while(tmp>0){
            for(int i=1;i<=200;i++){
                if(D[i]<=tmp){
                    cur+=D[i]*i;
                    tmp-=D[i];
                }
                else if(tmp<D[i]){
                    cur+=tmp*i;
                    tmp=0;
                }
            }
        }
        res=min(res,cur);
        for(int j=n[i-1];j<n[i];j++){
            D[G[j].d]++;
        }
    }
    printf("%d\n",res);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: