线段覆盖(序列动态规划+离散化)

线段覆盖

题目描述:
数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~10^18,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大。
输入描述:
第一行一个整数n,表示有多少条线段。
接下来n行每行三个整数, ai bi ci,分别代表第i条线段的左端点ai,右端点bi(保证左端点<右端点)和价值ci。
输出描述:
输出能够获得的最大价值
样例输入:
3
1 2 1
2 3 2
1 3 4
样例输出:
4
数据范围及提示:
n <= 1000000
0<=ai,bi<=10^18
0<=ci<=10^9
数据输出建议使用long long类型(Pascal为int64或者qword类型)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define in long long
using namespace std;
const in maxn=1000010;
struct node
{
    in l;
    in r;
    in v;
    bool operator < (node tmp)const
    {
        return r<tmp.r;
    }
}e[maxn];
in n,tot,a[maxn*2],f[maxn*2];
in init()
{
    in x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int main()
{
    n=init();
    for(in i=1;i<=n;i++)
    {
        e[i].l=init();e[i].r=init();e[i].v=init();
        a[++tot]=e[i].l,a[++tot]=e[i].r;
    }
    sort(a+1,a+tot+1);
    in sum=unique(a+1,a+tot+1)-(a+1);
    for(in i=1;i<=n;i++)
    {
        in tmp=lower_bound(a+1,a+sum+1,e[i].l)-a;
        e[i].l=tmp;
        tmp=lower_bound(a+1,a+sum+1,e[i].r)-a;
        e[i].r=tmp;
    }
    sort(e+1,e+n+1);
    int now=1;
    for(in i=1;i<=sum;i++)
    {
        f[i]=f[i-1];
        while(e[now].r==i)
        {
            f[i]=max(f[i],f[e[now].l]+e[now].v);
            now++;
        }
    }
    cout<<f[sum];
    return 0;
}
posted @ 2016-10-05 21:34  抽空的太阳  阅读(259)  评论(0编辑  收藏  举报