树状数组+快排 笨笨的西瓜种植(赛)

来源:互联网 发布:淘宝诈骗案例 编辑:程序博客网 时间:2024/04/27 16:32

背景 Background

笨笨:小西瓜,小西瓜~
路人甲:不会呀,这西瓜明明就大着啊……
笨笨:那……大西瓜,大西瓜~
路人甲:这么快就改口了……
笨笨:西瓜西瓜~可爱的西瓜~

描述 Description

笨笨种了一块西瓜地,但这块西瓜地的种植范围是一条直线的……
笨笨在一番研究过后,得出了m个结论,这m个结论可以使他收获的西瓜最多。
笨笨的结论是这样的:
从西瓜地B处到E处至少要种植T个西瓜,这个范围的收获就可以最大化。
笨笨不想那么辛苦,所以他想种植的西瓜尽量少,而又满足每一个所得的结论。

输入格式 Input Format
第一行两个数n,m(0<n<=5000,0<=m<=3000),表示笨笨的西瓜地长n,笨笨得出m个结论。
接下来m行表示笨笨的m个结论,每行三个数b,e,t(1<=b<=e<=n,0<=t<=e-b+1)。

输出格式 Output Format
输出笨笨最少需种植多少西瓜。

 

【参考程序】:
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;

struct node
{
    int b,e,t;
} a[3010];
int f[5010],c[5010];
int n,m;
int cmp(const void *s,const void *t)
{
    node i=*(node *)s,j=*(node *)t;
    return i.e-j.e;
}
int lowbit(int x)
{
    return x^(x&(x-1));
}
void modify(int x)
{
    while (x<=n)
    {
        c[x]++;
        x+=lowbit(x);
    }
}
int getsum(int x)
{
    int sum=0;
    while (x)
    {
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].b,&a[i].e,&a[i].t);
    qsort(a+1,m,sizeof(node),cmp);
    memset(c,0,sizeof(c));
    memset(f,0,sizeof(f));
    int need,ans=0;
    for (int i=1;i<=m;i++)
    {//当前这个结论还需种多少个西瓜才满足
        need=a[i].t-(getsum(a[i].e)-getsum(a[i].b-1));
        for (int j=a[i].e;j>=a[i].b;j--)
        {
            if (need<=0) break;
            if (!f[j])
            {
                f[j]=1; need--;
                modify(j); ans++;
            }
        }
    }
    printf("%d/n",ans);
    return 0;
}