#include
#include
#define maxn 1000000+5
using namespace std;
struct line{
int b,e;
friend bool operator < (line x,line y){
if(x.e!=y.e)return x.ey.b;
}
}l[maxn];
int main(){
ios::sync_with_stdio(false);
int n,i,j,k,x,y;cin>>n;
for(i=1;i<=n;i++){
cin>>x>>y;
if(x>y)swap(x,y);
l[i].b=x;l[i].e=y;
}
sort(l+1,l+n+1);
int pos=-1,cnt=0;i=1;
while(i<=n){
if(l[i].b>=pos){
cnt++;
pos=l[i].e;
}
i++;
}
cout<
但是对于线段有权值的情况,可以证明贪心是行不通的,这时候就必须DP
我的做法是:设dp[I]表示到第i条线段可获得的最大价值,容易得到这样的状态转移方程:
dp[I]=max(dp[I-1],dp[j]+line[i].c),j表示距离i最近的与i没有交集的线段。
对于查找线段j,朴素的做法就是从i开始向前枚举,然而这样只能通过线段覆盖2,对于4会TLE两个点,5会TLE7个点。
仔细分析线段性质,可以发现由于我们对线段进行了排序,所以线段的末端点对于线段的编号是具有单调性的,所以可以使用二分查找第一个满足此性质的线段。
#include
#include
#define int long long
#define maxn 1000000+5
using namespace std;
struct line{
int b,e,c;//begin,end,cost
friend bool operator < (line x,line y){
if(x.e!=y.e)return x.e>1;
if(l[mid].e>l[i].b){
ri=mid-1;
}
else if(l[mid].e<=l[i].b){
lf=mid+1;
}
}
if(l[lf].e<=l[i].b)return lf;
return lf-1;
}
else{//朴素查找
int p=i;
while(l[p].e>l[i].b)p--;
return p;
}
}
#undef int
int main(){
ios::sync_with_stdio(false);
int n,i,j,k;cin>>n;
for(i=1;i<=n;i++){
cin>>x>>y>>z;
l[i].b=x;l[i].e=y;l[i].c=z;
}
sort(l+1,l+n+1);
l[0].b=l[0].e=l[0].c=-1;
for(int i=1;i<=n;i++)
dp[i]=max(dp[i-1],dp[bsearch(i,0)]+l[i].c);
cout<
然而还有另一种DP思路,(%ZY),设dp[I]表示在坐标I的最大价值,可行的一种状态转移方程为:
f[line[I].e]=max(f[line[I].e],f[line[I].b]+line[I].c);
转移时枚举line[I].e而不是每个坐标
在每次循环时,拿f[line[I].e]来更新从f[Iine[I].e+1]到f[Iine[I+1].e]中的所有点,这样可以实现在转移时选或不选这条线段的操作。
对于线段覆盖4、5,数据范围过大,需要离散化。
#include
#include
#include
using namespace std;
struct segment
{
long long b,e,c;
}a[1000005];
struct mes
{
long long pos,rank;
}t;
long long n,i,j,pre,p,f[1000005];
struct cmp2
{
bool operator()(mes x,mes y)
{
return x.pos>=y.pos;
}
};
priority_queue,cmp2> q;
bool cmp(segment x,segment y)
{
return x.e>n;
for(i=1;i<=n;i++)
{
cin>>a[i].b>>a[i].e>>a[i].c;
q.push((mes){a[i].b,(i<<1)-1});//奇数节点为begin
q.push((mes){a[i].e,i<<1});//偶数节点为end
}
pre=q.top().pos;
for(i=1;i<=n+n;i++)
{//离散化
t=q.top();
q.pop();
if(t.pos!=pre)//如果两个点的坐标不相同
{
++p;
pre=t.pos;
}
if((t.rank&1)==1) a[(t.rank+1)>>1].b=p;
else a[(t.rank)>>1].e=p;
}
sort(a+1,a+n+1,cmp);
for(i=1;i