YJJ's Salesman HDU - 6447(线段树 单点更新+DP思想)

版权声明:欢迎大家指正错误,有不同观点的欢迎评论,共同进步 https://blog.csdn.net/Sirius_han/article/details/82114301

YJJ's Salesman

题目链接:HDU - 6447

题意:一个1e9*1e9的地图,要求由(0, 0) -> (1e9, 1e9);只能向下,向右, 向右下移动;地图中有n个点,有宝藏,只有从该点的左上方移动过来才能拿走宝藏,问最多能拿走多少宝藏;

本题和之前做过的一个数星星题有点相似, 题目链接:POJ - 2352  

根据题意可知在每一个点能拿到的宝藏一定是其左上方的点,那么就是找这个点的左上方的点的宝藏总和;可以用线段树维护;怎么维护呢?

把y坐标当做需要维护的区间值,然后向线段树里插点,计算的时候就是计算区间[1, y]的值,那么。x坐标一定是由小到大向线段树里插才不会漏掉点,而对于y坐标,要由大到小插点才不会将在计算到同一行的点;这样就只记录了左上方的点;插点的时候插入的值不单单是将要插入的点的宝藏值,还包括有左上方走过来得到的最大宝藏;因为并不是左上方的所有点的宝藏都能拿到手,只计算在左上方能拿到的最大宝藏就ok了, 确实DP的思想;

再一点,本体需要离散化;

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct point{
	int x, y, val;
	bool operator < (const point& a)const{
		if(x==a.x) return y>a.y;
		return x<a.x;
	}
}p[maxn];
int t[maxn];
struct node{
	int l, r, val;
}tr[maxn<<2];
void pushup(int m){	
	tr[m].val=max(tr[m<<1].val, tr[m<<1|1].val);
}
void build(int m, int l, int r){
	tr[m].l=l;
	tr[m].r=r;
	tr[m].val=0;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(m<<1, l, mid);
	build(m<<1|1, mid+1, r);
}
void updata(int m, int x, int val){
	if(tr[m].l==x&&tr[m].r==x){
		tr[m].val=max(tr[m].val, val);
		return;
	}
	int mid=(tr[m].l+tr[m].r)>>1;
	if(x<=mid) updata(m<<1, x, val);
	else updata(m<<1|1, x, val);
	pushup(m);
}
int query(int m, int l, int r){
	if(tr[m].l==l&&tr[m].r==r){
		return tr[m].val;
	}
	int mid=(tr[m].l+tr[m].r)>>1;
	if(r<=mid) return query(m<<1, l, r);
	else if(l>mid) return query(m<<1|1, l, r);
	else return max(query(m<<1, l, mid), query(m<<1|1, mid+1, r));
}
int main(){
	int T;
	scanf("%d", &T);
	while(T--){
		int n;
		scanf("%d", &n);
		for(int i=1; i<=n; i++){
			scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].val);
			t[i]=p[i].y;
		}
		sort(t+1, t+1+n);
		int cnt=unique(t+1, t+1+n)-(t+1);
		for(int i=1; i<=n; i++){
			p[i].y=lower_bound(t+1, t+1+n, p[i].y)-t;
		}
		sort(p+1, p+1+n);
		build(1, 1, n);
		int ans=0, temp=0;
		for(int i=1; i<=n; i++){
			if(p[i].y==1){
				temp=0;
				updata(1, 1, p[i].val);
			}
			else{
				temp=query(1, 1, p[i].y-1);
				updata(1, p[i].y, temp+p[i].val);
			}
			ans=max(ans, temp+p[i].val);
		}
		printf("%d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Sirius_han/article/details/82114301