线段覆盖(序列动态规划+离散化)
线段覆盖
题目描述:
数轴上有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;
}