思路:
感觉像是背包问题的变形…
很直接的DP策略:
首先先对物体进行排序,外半径大的先处理。(考虑无后效性,因为对于外半径最大的物品是不能堆在其他物品上面的。)
设dp[i]是处理到第i个物体时可以达到的最高高度。
则
dp[i] = max{dp[j]} + h[i]
其中 1 <= j < i && b[i] > a[j]。
故需要动态维护区间最值,可用线段树或树状数组的写法
代码:
数组数组:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll INF = 1e16 + 7;
const int A = 1e6 + 10;
class P{
public:
int n;
ll tree[A<<1];
void init(int _n){
n = _n;
for(int i=1 ;i<=n ;i++){
tree[i] = -INF;
}
}
ll query(int pos){
ll res = -INF;
for(int i=pos ;i>0 ;i-=(i&(-i))) res = max(res,tree[i]);
return res;
}
void update(int pos,ll val){
for(int i=pos ;i<=n ;i+=(i&(-i))) tree[i] = max(tree[i],val);
}
}bit;
class Node{
public:
int a,b,h;
bool operator <(const Node& rhs) const{
if(b == rhs.b) return a > rhs.a;
return b > rhs.b;
}
}x[A];
int y[A<<1];
int main(){
int n;
scanf("%d",&n);
int tot = 0;
for(int i=1 ;i<=n ;i++){
scanf("%d%d%d",&x[i].a,&x[i].b,&x[i].h);
y[tot++] = x[i].a;
y[tot++] = x[i].b;
}
sort(y,y+tot);
tot = unique(y,y+tot) - y;
for(int i=1 ;i<=n ;i++){
x[i].a = lower_bound(y,y+tot,x[i].a) - y + 1;
x[i].b = lower_bound(y,y+tot,x[i].b) - y + 1;
}
sort(x+1,x+n+1);
bit.init(2*n);
ll ans = -INF;
for(int i=1 ;i<=n ;i++){
ll now = max(0LL,bit.query(x[i].b-1)) + x[i].h;
ans = max(ans,now);
bit.update(x[i].a,now);
}
printf("%I64d\n",ans);
return 0;
}
线段树:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll INF = 1e16 + 7;
const int A = 1e6 + 10;
class P{
public:
int l,r;
ll Max;
}tree[A<<2];
class Node{
public:
int a,b,h;
bool operator <(const Node& rhs) const{
if(b == rhs.b) return a > rhs.a;
return b > rhs.b;
}
}x[A];
int y[A<<1];
void push_up(int id){
tree[id].Max = max(tree[id<<1].Max,tree[id<<1|1].Max);
}
void build_Tree(int id,int l,int r){
tree[id].l = l,tree[id].r = r;
tree[id].Max = 0;
if(l == r) return;
int mid = (l+r)>>1;
build_Tree(id<<1,l,mid);
build_Tree(id<<1|1,mid+1,r);
}
ll query(int id,int st,int ed){
int l = tree[id].l,r = tree[id].r;
if(st <= l && r <= ed) return tree[id].Max;
int mid = (l+r)>>1;
ll res = 0;
if(st <= mid) res = max(res,query(id<<1,st,ed));
if(ed > mid) res = max(res,query(id<<1|1,st,ed));
return res;
}
void update(int id,int pos,ll val){
int l = tree[id].l,r = tree[id].r;
if(l == r){
tree[id].Max = max(tree[id].Max,val);
return;
}
int mid = (l+r)>>1;
if(pos <= mid) update(id<<1,pos,val);
else update(id<<1|1,pos,val);
push_up(id);
}
int main(){
int n;
scanf("%d",&n);
int tot = 0;
for(int i=1 ;i<=n ;i++){
scanf("%d%d%d",&x[i].a,&x[i].b,&x[i].h);
y[tot++] = x[i].a;
y[tot++] = x[i].b;
}
sort(y,y+tot);
tot = unique(y,y+tot) - y;
int m = 0;
for(int i=1 ;i<=n ;i++){
x[i].a = lower_bound(y,y+tot,x[i].a) - y + 1;
x[i].b = lower_bound(y,y+tot,x[i].b) - y + 1;
m = max(m,x[i].a),m = max(m,x[i].b);
}
sort(x+1,x+n+1);
build_Tree(1,1,m);
ll ans = -INF;
for(int i=1 ;i<=n ;i++){
ll now = query(1,1,x[i].b-1) + x[i].h;
ans = max(ans,now);
update(1,x[i].a,now);
}
printf("%I64d\n",ans);
return 0;
}