题意:
给定n个点,每个点有个权值,只有从这个点的左下方45°上来,才能获得这个点的权值,每次只能从某个点往上走一格或往右走一格,或往右上走一格,
问:找一条路径,使获得权值最大;
思路:
首先我们能够想到对于A点(x1,y1),它的最优值应该是由某个 B点(x2,y2) && x2<x1 && y2<y1 得来的,如果遍历的话 n^2 复杂度不能接受,所以对于点A,我们要想办法快速的得到上述满足B点的最大值,
首先按照x坐标从小到大排序,这样从前往后遍历的时候,当前点前面的点的x 坐标是满足条件的(如果有x坐标相同的情况,另行处理),我们只要查找y坐标满足情况的最大值就ok了,,这样我们会想到离散化每个点的y坐标,然后按 y坐标建的线段树,维护最大值,,
为了解决上述的x坐标相同的情况,我们先把x相同的点存起来,如果后续遇到跟他不同的点,再更新线段树;
#include<iostream>
#include <cstdio>
#include<algorithm>
#include <cstring>
#include <set>
#include <bitset>
#include <map>
using namespace std;
typedef pair<int,int> P;
typedef long long ll;
const int maxn = 1e5 + 7;
const int INF = 0x3f3f3f3f;
map<int, int> mp;
struct node {
int x;
int y;
int ny;
int v;
}a[maxn];
bool cmp(node a,node b) {
if(a.x == b.x) {
return a.y < b.y;
}
return a.x < b.x;
}
int n;
int b[maxn];
void init() {
mp.clear();
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].v);
b[i] = a[i].y;
}
sort(b+1,b+1+n);
sort(a+1,a+1+n, cmp);
int t = -1, id = 1;
for(int i = 1; i <= n; ++i) {
if(b[i] != t) {
mp[b[i]] = id++;
t = b[i];
}
else mp[b[i]] = mp[b[i-1]];
}
for(int i = 1; i <= n; ++i) {
a[i].ny = mp[a[i].y];
}
}
int max_[maxn<<2];
int query(int id, int l_, int r_, int ql, int qr) {
if(r_ < ql || l_ > qr) return 0;
if(ql == l_ && qr == r_) {
return max_[id];
}
int mid = (l_ + r_) / 2;
if(ql > mid) {
return (query((id<<1)|1, mid+1, r_, ql, qr));
}
else if(qr <= mid) {
return (query((id<<1), l_, mid, ql, qr));
}
else {
return max((query((id<<1), l_, mid, ql, mid)),(query((id<<1)|1, mid+1, r_, mid+1, qr)));
}
}
void push_up(int id) {
max_[id] = max(max_[(id<<1)], max_[(id<<1)|1]);
}
void update(int id, int l_, int r_, int ul, int ur, int v) {
if(l_ == r_ && ul == ur) {
max_[id] = max(max_[id], v);
return;
}
int mid = (l_ + r_) / 2;
if(ul > mid) {
update((id<<1|1),mid+1, r_, ul, ur, v);
}
else if(ur <= mid) {
update((id<<1),l_, mid, ul, ur, v);
}
else {
update((id<<1),l_, mid, ul, mid, v);
update((id<<1)|1,mid+1, r_, mid+1, ur, v);
}
push_up(id);
}
int dp[maxn];
int main() {
int T;
scanf("%d", &T);
while(T--) {
init();
memset(max_, 0, sizeof max_);
memset(dp, 0, sizeof dp);
int ans = 0, xx = -1;
set<P> st;
for(int i = 1; i <= n; ++i) {
if(a[i].x != xx) {
for(auto p : st) {
update(1, 1, n, p.first, p.first, p.second);
}
st.clear();
xx = a[i].x;
}
int ny = a[i].ny;
int maxt = query(1,1,n,1,ny-1);
dp[i] = maxt+a[i].v;
st.insert(P(a[i].ny,dp[i]));
ans = max(ans, dp[i]);
}
printf("%d\n", ans);
}
return 0 ;
}