鸡国福利

鸡国福利

时间限制: 1 Sec  内存限制: 128 MB

题目描述

鸡国为了表彰鸡国每一只鸡在过去一年的优秀表现,打算在接下来的 n 天中每天给鸡国的一只鸡发 1 袋或者 2 袋“鸡币”(鸡国的通用货币)作为福利。国王要求每天来领钱鸡
互不相同,即来领过钱的鸡不能再来,否则将受到严厉的处罚。 
但聪明的鸡国老百姓侦察后发现国王每天发的钱袋子里面装的钱数量是不一样的(同一天的相同),第 i 天发的每一袋钱为 a i 元。如果第 i 天来领钱的鸡领 1 袋钱,它可以获得ai 元的“鸡币”,如果它领 2 袋钱,则可以获得 2×ai 元“鸡币”,当然它也可以放弃,则第i 天的钱国王收回国库。 
由于鸡国生活条件优越和鸡的贪念等原因,当第 i 天领钱的鸡同时满足以下两个条件时它才会感到幸福: 
(1)领到的钱不能低于鸡国的平均收入 m 元。 
(2)要跟它前面领了钱且感到幸福的鸡一样幸福或者更幸福。 
仁慈的国王希望鸡国的每一只鸡都能感到幸福,请你帮国王规划一下在这 n 天中怎样给每一只发钱才能让最多的鸡感到幸福? 

输入

输入共 2 行。 
第 1 行输入两个整数 n 和 m,分别表示发钱的天数(或理解为来领钱的鸡数)和鸡国的平均收入。 
第 2 行 n 个正整数 ai  (1≤i≤n),依次表示第 i 天发的一袋钱中的“鸡币”为 ai 元。。 

输出

输出 1 行一个整数,表示最多可以让多少只鸡感到幸福。 

样例输入

2 1
2 1

样例输出

2
分析:题意是有n天,每天有a[i],2*a[i],选其中一个,或者不选,问最长不减子序列的长度;
   首先可以想到dp[i] = max (dp[i-j]) + 1 ,i>=m&&i-j>=m , j>=0;
   dp[i] 表示当前得到钱数最大不超过 i 的最多个数;
   这样是O(N2)的复杂度,然后 max(dp[i-j]) 其实是前缀的最大值,可以用树状数组或线段树维护;
   这样复杂度是O(Nlog N);
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#define rep(i,m,n) for(i=m;i<=(int)n;i++)
#define mod 100000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
#define ls rt<<1
#define rs rt<<1|1
#define all(x) x.begin(),x.end()
const int maxn=2e5+10;
const int N=5e2+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
ll qpow(ll p,ll q,ll mo){ll f=1;while(q){if(q&1)f=qmul(f,p,mo)%mo;p=qmul(p,p,mo)%mo;q>>=1;}return f;}
int n,m,k,t,a[maxn],d[maxn],b[maxn],cnt,c[maxn];
void add(int x,int y)
{
    while(x<=cnt)d[x]=max(d[x],y),x+=x&(-x);
}
int get(int x)
{
    int ret=0;
    while(x)ret=max(ret,d[x]),x-=x&(-x);
    return ret;
}
int main()
{
    int i,j;
    scanf("%d%d",&n,&m);
    b[++cnt]=m;
    rep(i,1,n)scanf("%d",&a[i]),b[++cnt]=a[i],b[++cnt]=2*a[i];
    sort(b+1,b+cnt+1);
    cnt=unique(b+1,b+cnt+1)-b-1;
    m=lower_bound(b+1,b+cnt+1,m)-b;
    rep(i,1,n)c[i]=lower_bound(b+1,b+cnt+1,2*a[i])-b,a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
    int ret=0;
    rep(i,1,n)
    {
        int ok1,ok2;
        if(a[i]>=m)
        {
            ok1=get(a[i]);
            ret=max(ret,ok1+1);
        }
        if(c[i]>=m)
        {
            ok2=get(c[i]);
            ret=max(ret,ok2+1);
        }
        if(a[i]>=m)
        {
            add(a[i],ok1+1);
        }
        if(c[i]>=m)
        {
            add(c[i],ok2+1);
        }
    }
    printf("%d\n",ret);
    return 0;
}
posted @ 2017-07-24 22:32  mxzf0213  阅读(897)  评论(2编辑  收藏  举报