传送门:POJ3616
题意:给出n个带权区间,要求从这n个区间中选取一个元素互不相交的子集,使得子集元素的权重和最大。
思路:我自己的思路是dp[i]表示右端点小于等于i的所有区间所能得到的最大权重,然而因为按左端点排序排习惯了wa了好久。。
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,x,n) for(int i=x;i<n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
using namespace std;
typedef pair<int,int>P;
const int MAXN=100010;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
struct node
{
int l,r,w;
bool operator < (node a) const
{
return r < a.r;
}
}p[MAXN];
int dp[MAXN * 20];
int main()
{
int n, m, r;
cin >> n >> m >> r;
for(int i = 0; i < m; i++)
{
scanf("%d %d %d", &p[i].l, &p[i].r, &p[i].w);
p[i].r += r;
}
sort(p, p + m);
int cnt = 0;
for(int i = 1; i <= n + r; i++)
{
dp[i] = dp[i - 1];
while(cnt < m && p[cnt].r == i)
{
dp[i] = max(dp[i], dp[p[cnt].l] + p[cnt].w);
cnt++;
}
}
/*for(int i = 1; i <= n + 2; i++)
cout << dp[i] << " ";
cout << endl;*/
cout << *max_element(dp, dp + n + r + 1) << endl;
return 0;
}
网上的dalao们大部分都是按类似于LIS的方法做的,将区间按左端点排序后,dp[i]表示到第i个区间为止能得到的最大权重。就这个题而言我的想法的复杂度和dalao们的做法是差不多的,因为这个题区间最大只有2e6的大小,然而如果区间端点的范围再扩大一些我就gg了。。
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,x,n) for(int i=x;i<n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
using namespace std;
typedef pair<int,int>P;
const int MAXN=100010;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
struct node
{
int l,r,w;
bool operator < (node a) const
{
if(l == a.l) return r < a.r;
return l < a.l;
}
}p[MAXN];
int dp[MAXN * 20];
int main()
{
int n, m, r;
cin >> n >> m >> r;
for(int i = 0; i < m; i++)
{
scanf("%d %d %d", &p[i].l, &p[i].r, &p[i].w);
p[i].r += r;
}
sort(p, p + m);
for(int i = 0; i < m; i++)
{
dp[i] = p[i].w;
for(int j = 0; j < i; j++)
{
if(p[j].r <= p[i].l)
dp[i] = max(dp[i], dp[j] + p[i].w);
}
}
cout << *max_element(dp, dp + m) << endl;
return 0;
}