HDU-6447-YJJ's Salesman(离散化+01dp,线段树维护)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6447

Problem Description

YJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the way to destination.
One day, he is going to travel from city A to southeastern city B. Let us assume that A is (0,0) on the rectangle map and B (109,109) . YJJ is so busy so he never turn back or go twice the same way, he will only move to east, south or southeast, which means, if YJJ is at (x,y) now (0≤x≤109,0≤y≤109) , he will only forward to (x+1,y) , (x,y+1) or (x+1,y+1) .
On the rectangle map from (0,0) to (109,109) , there are several villages scattering on the map. Villagers will do business deals with salesmen from northwestern, but not northern or western. In mathematical language, this means when there is a village k on (xk,yk) (1≤xk≤109,1≤yk≤109) , only the one who was from (xk−1,yk−1) to (xk,yk) will be able to earn vk dollars.(YJJ may get different number of dollars from different village.)
YJJ has no time to plan the path, can you help him to find maximum of dollars YJJ can get.

 

Input

The first line of the input contains an integer T (1≤T≤10) ,which is the number of test cases.

In each case, the first line of the input contains an integer N (1≤N≤105) .The following N lines, the k -th line contains 3 integers, xk,yk,vk (0≤vk≤103) , which indicate that there is a village on (xk,yk) and he can get vk dollars in that village.
The positions of each village is distinct.

 

Output

The maximum of dollars YJJ can get.

 

Sample Input

1

3

1 1 1

1 2 2

3 3 1

 

Sample Output

3

题目大意:在一个10^9*10^9的地图上,分布着10^5个村庄,一个人从0,0,处出发,前往10^9,10^9处,中间经过村庄可以获得村庄的宝藏,但是只有从村庄(x,y)的(x-1,y-1)坐标进入村庄才会获得宝藏,输出一个人从起点到终点能够获得的最多的宝藏;

一开始想的是DP,但是一看10^9的地图.....直接放弃,虽然想到离散化,但是不知道怎么离散化,结果到比赛结束也没有写出来..好菜,按照坐标离散化,之后建一个01dp;

状态转移方程:dp[x]=max(dp[x-1],dp[x]);用上线段树去维护这个dp

ac:

#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>
#include<iostream>  
#include<algorithm>  
using namespace std;  

#define ll long long  
#define INF 0x3f3f3f3f  
//#define mod 1e9+7
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
//std::ios::sync_with_stdio(false);

const int MAXN=2e5+10;
const ll mod=1e9+7;
struct dot{
	int x,y;
	ll v;
}dots[MAXN];
ll tree[MAXN<<2];
ll dp[MAXN];
int num[MAXN];
int n;

void intt()
{
	clean(dp,0);
	clean(tree,0);
	clean(num,0);
}

bool cmp1(dot a,dot b)
{
	return a.x<b.x;
}

bool cmp2(dot a,dot b)
{
	return a.y<b.y;
}

void updata(int L,ll x,int l,int r,int rt)
{
	if(l==r)
	{
		tree[rt]=max(x,tree[rt]);
		return ;
	}
	int mid=(l+r)>>1;
	if(L<=mid)
		updata(L,x,l,mid,rt<<1);
	else
		updata(L,x,mid+1,r,rt<<1|1);
	tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}

ll Query(int L,int R,int l,int r,int rt)
{
	if(l>=L&&r<=R)
		return tree[rt];
	int mid=(l+r)>>1;
	ll ans=0;
	if(L<=mid)
		ans=max(ans,Query(L,R,l,mid,rt<<1));
	if(R>mid)
		ans=max(ans,Query(L,R,mid+1,r,rt<<1|1));
	return ans;
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		intt();
		scanf("%d",&n);
		for(int i=1;i<=n;++i)
			scanf("%d%d%lld",&dots[i].x,&dots[i].y,&dots[i].v);
		sort(dots+1,dots+n+1,cmp1);
		int temp=dots[1].x,id=1;//离散x 
		dots[1].x=id;
		for(int i=2;i<=n;++i)
		{
			if(dots[i].x==temp)
				dots[i].x=id;
			else
			{
				temp=dots[i].x;
				dots[i].x=++id;
			}
		}
		sort(dots+1,dots+1+n,cmp2);
		temp=dots[1].y,id=1;//离散y 
		dots[1].y=id;
		num[id]=1;
		for(int i=2;i<=n;++i)
		{
			if(dots[i].y==temp)
				dots[i].y=id;
			else
			{
				temp=dots[i].y;
				dots[i].y=++id;
			}
			num[id]++;
		}
		//离散化正确 
		id=0;
		int x,y;
		ll v;
		for(int i=1;i<=n;++i)//便利n个y 
		{
			for(int j=1;j<=num[i];++j)
			{
				int k=j+id;
				x=dots[k].x,y=dots[k].y,v=dots[k].v;
				if(x==1)//该位置的x是1,之前没有东西 
					dp[x]=v;
				else
				{
					ll ans1=Query(1,x-1,1,n,1)+v;
					ll ans2=Query(1,x,1,n,1);
					//cout<<ans1<<" "<<ans2<<endl;
					dp[x]=max(ans1,ans2);
				}
			}
			for(int j=1;j<=num[i];++j)
			{
				int k=j+id;
				x=dots[k].x,y=dots[k].y,v=dots[k].v;
				updata(x,dp[x],1,n,1);//将该位置的dp值放入数组 
			}
//			for(int j=1;j<=n<<2;++j)
//				cout<<tree[j]<<" ";
//			cout<<endl;
//			for(int j=1;j<=n;++j)
//				cout<<dp[j]<<" ";
//			cout<<endl;
			id=id+num[i];
		}
//		for(int i=1;i<=n<<2;++i)
//			cout<<tree[i]<<endl;
		printf("%lld\n",tree[1]);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/82152477