Chieh's Blog

Because Of Coding

R311 DIV2 C. Arthur and Table

Chieh posted @ 2015年7月01日 21:59 in codeforces , 353 阅读

飞机票:http://codeforces.com/contest/557/problem/C

题意:给你个桌子,有n个桌脚(n<=1e5),每个桌脚有个高度为ai,拆掉每个桌脚需要力量bi,现在问你拆除桌脚使桌子稳定,且用力最小,桌子稳定的条件是最大的那个脚的总数必须大于当前脚数量的一半,假设有当前有5个桌脚,要使稳定,需要3个最大的脚,假设4个,则要3个最大脚,只有1个他就是稳定的。

分析:我们可以枚举脚的长度,怎么枚举??按脚长度排个序,然后假设长度为k的脚的数量从l到r,即有r-l+1个为k的数量。然后我们可以来个辅助数组ci,就是大于k脚长度需要花费的总力气,这个力气可以从后往前推,因为我们是从小到大对脚长度进行排序,那么初始必须花费的力气是c[r+1],然后我们有r-l+1的数量,设为sum,则我们可以保留sum-1(因为大于一半)个脚,因为前面有l-1个脚,我们可以拆除l-1-(sum-1)个脚。设为des,如果des<=0,则不用拆了,因为我们已经足够,如果大于0,则要从前面l-1选择des个脚拆除,我们贪心的话,肯定会拆需要力量最小的脚,因为力量<=200,所以我们可以用个数组need[200]表示前面各个力量有多少个然后从小到达选择des个,设为力量需要为p,这总共需要力量c[r+1]+p,然后去最小值因为我们要处理need[200],所以我们要一个辅助数组记录l到r需要的各个力量,然后处理完l~r则把辅助数组的数据加到need上去,让下一次可以继续迭代,复杂度O(n*200),最后啪啪啪就可以AC了

/*
Author:Chieh
Because Of Coding
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#define LL long long
#define INF 1e9
#define EPS 1e-9
using namespace std;
const int maxn=123456;
int n;
struct he
{
    int len,val;
} Sky[maxn];
bool cmp(he a, he b)
{
    return a.len<b.len;
}
int bi[maxn];
int ai[234];
int ci[234];
void init()
{
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&Sky[i].len);
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&Sky[i].val);
    }
    sort(Sky+1,Sky+1+n,cmp);
    bi[n+1]=0;
    for(int i=n; i>=1; i--)
    {
        bi[i]=Sky[i].val;
        bi[i]+=bi[i+1];
    }
    Sky[n+1].len=INF;
    Sky[0].len=0;

}

void play()
{
    memset(ai,0,sizeof(ai));
    int l=-1;
    int MIN=INF;
    memset(ci,0,sizeof(ci));
    for(int i=1; i<=n+1; i++)
    {
        if(Sky[i].len!=Sky[i-1].len)
        {
            if(l!=-1)
            {
                int ok=(i-1-l)+1;
                int xy=ok-1;
                xy=l-1-xy;
                int sum=bi[i];
                if(xy>0)
                {
                    for(int j=1; j<=200; j++)
                    {
                        if(xy<=ai[j])
                        {
                            sum+=xy*j;
                            break;
                        }
                        else
                        {
                            xy-=ai[j];
                            sum+=ai[j]*j;
                        }
                    }
                }
                if(sum<MIN)MIN=sum;
            }
            for(int j=1; j<=200; j++)
            {
                ai[j]+=ci[j];
            }
            l=i;
            memset(ci,0,sizeof(ci));
            int v=Sky[i].val;
            ci[v]++;
        }
        else
        {
            int v=Sky[i].val;
            ci[v]++;
        }
    }
    printf("%d\n",MIN);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        init();
        play();
    }
//    cout << "Hello world!" << endl;
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter