zhao_ry514114
赵若伊

导航

 

原题(P1868 饥饿的奶牛)

记录传送门

题意

在n个区间里取若干个区间,使它们互不重合且覆盖长度最大

标签给的很明确了就是dp,线性

思路

用vector记录每一个右端点的左端点

遍历右端点

再遍历它的左端点

两种情况:

  • 如果这段区间要取,就要取这段区间之前的最大值+区间长度
  • 如果不取,就是算出来的上一个最大值(即右端点前一个)

所以dp方程:

dp[右端点]=max(dp[右端点],dp[左端点-1]+区间长度)

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 3000010;
vector<int> a[N];
int dp[N];
int main(){
	int n;
	cin>>n;
	int maxn=INT_MIN;//右端点最大值
	while(n--){
		int x,y;
		cin>>x>>y;
		a[y].push_back(x);//储存每个右端点对应的左端点
		maxn=max(maxn,y);
	}
	for(int i=0;i<=maxn;i++){
          //初始化
        if(i==0){
            dp[i]=0;
        }
        else dp[i]=dp[i-1];
        if(i!=0){
          //遍历左端点(如果没有左端点不会进此循环)
            for(auto j:a[i]){
                if(j!=0){
                	dp[i]=max(dp[i],dp[j-1]+(i-j+1));//dp方程
                }
                else dp[i]=max(dp[i],i-j+1);//当j为0时dp[j-1]会越界,要特殊处理
            }
        }
	}
	cout<<dp[maxn];
	return 0;
}
posted on 2025-08-25 18:35  zhao_ry514114  阅读(8)  评论(0)    收藏  举报