CCPC 2018 网络赛 Problem J Hdu6447 YJJ's Salesman

传送门

题目大意:

给定一个二维平面(0

求最大价值。

输入:T组数据,包含N(N个村庄)T<=10

每组数据共N行,X,Y,V分别表示坐标和价值,N<=1e5

样例

输入:

1

3

1 1 1

1 2 2

3 3 1

输出 :

3

思路:

不考虑区间大小的话,定义dp[x][y]表示到达坐标x,y时的最大价值,a[x][y]表示位置为(x,y)的村庄的价值

那么dp[x][y]=max(dp[x-1][y-1]+a[x][y],dp[x-1][y],dp[x][y-1])

但是由于坐标  x,y<1e9 

所以可以直接对所有坐标进行离散化。

接下来考虑对转移进行优化,

dp[x][y]可以由dp[1~x-1][1~y-1]当中的最大值转移过来

那么直接排序后用树状数组维护区间最大值就好了

什么,你说要用二维树状数组?你不慌,且听我慢慢解释

首先对于所有的村庄,首先按照从左往右从上往下排序,这样村庄就是x坐标相同的。

对于每一个x相同的坐标查询1-(y-1)区间的最值,然后当一整列(x相同)的村庄信息处理完后,将这一列每一个dp值插入树状数组(维护最大值,位置为y)。

因为将村庄的x坐标从小到大排序,已经存在的信息只能是当前村庄左边的村庄,然后树状数组查询的是从1-y-1的区间最值,结合一下就是从1~x-1和1~y-1的区间最值

 

详细怎么用代码实现,请看下面代码中的注释

代码:

#include
#include
#include
#include
#include
#include
#define lowbit(x) (((x)&-(x)))
#define MAXN 100006
#define pr(x) printf("%d\n",(x))//DEBUG
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
int c[MAXN+10];
int n,m;
inline void modify(int x,int v)
{
	while(x<=MAXN)
	{
		c[x]=max(c[x],v);
		x+=lowbit(x);
	}
}
inline int query(int x)
{
	int f=0;
	while(x>0)
	{
		f=max(f,c[x]);
		x-=lowbit(x);
	}
	return f;
}
struct vill
{
	int x,y,v;
}sa[MAXN];
bool operator<(vill a,vill b)
{
	if(a.x==b.x)return a.y

 

你可能感兴趣的:(数据结构)