HDU 6447 - YJJ's Salesman - [树状数组优化DP][2018CCPC网络选拔赛第10题]
题目链接: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
Source
2018中国大学生程序设计竞赛 - 网络选拔赛
题意:
从 $(0,0)$ 往 $(10^9,10^9)$ 走,每次只能从 $\left( {x,y} \right)$ 走到 $\left( {x + 1,y} \right)$ 或者 $\left( {x,y + 1} \right)$ 或者 $\left( {x + 1,y + 1} \right)$,不能折返,不能走重复的路,
在地图上分布着一些村庄,给出村庄的坐标 $\left( {x,y} \right)$ 和 $v$ 值,当且仅当你从 $\left( {x - 1,y - 1} \right)$ 走到村庄时,你才可以获得 $v$,求最大能获得多少 $v$。
题解:
显然,假设我走到了某一个村庄 $\left( {x_0,y_0} \right)$,那么只有在 $x \ge x_0 + 1$ 且 $y \ge y_0 + 1$ 范围内的村庄,能使得我的 $v$ 值进一步增加,
换句话说,我走到了某一个村庄 $\left( {x_0,y_0} \right)$,我上一个走到的“有意义的”村庄必然是在 $x \le x_0 - 1$ 且 $y \le y_0 - 1$ 的范围内的,
那么我就要在 $x \le x_0 - 1$ 且 $y \le y_0 - 1$ 的范围内找到某个村庄,我走到该村庄时,我获得的 $v$ 值时最大的,
故,我们假设 $dp\left[ i \right]$ 为走到村庄 $i$ 时能获得的最大的 $v$,则状态转移方程为:
$dp\left[ i \right] = \max \left( {dp\left[ j \right] + v\left[ i \right]} \right)$,其中村庄 $j$ 的坐标 $\left( {x,y} \right)$ 满足 $x \le x_0 - 1$ 且 $y \le y_0 - 1$
那么,简单地说,对于每个村庄,要能 $O\left( {\log n} \right)$ 获得某区域内的最大值,同时也要能 $O\left( {\log n} \right)$ 的某区域内的最大值,自然而然想到树状数组……
我们离散化纵坐标,并且从小到大枚举横坐标,用树状数组维护纵坐标为 $\left[ 1,y \right]$ 区域内最大的dp[i],
1、计算到某个横坐标值上某一村庄 $dp\left[ i \right]$,假设其纵坐标为 $y$,查询 $\left[ 1,y - 1 \right]$ 区域内最大值;
2、每次计算完某个横坐标值的一竖条上的所有村庄的 $dp\left[ i \right]$,将这一竖条上所有的 $dp\left[ i \right]$ 全部拿去更新树状数组。
AC代码:
#include<bits/stdc++.h>
using namespace std; const int maxn=1e5+; struct Node{
int x,y,v;
}node[maxn];
bool cmp(Node a,Node b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x<b.x;
} int n;
int dp[maxn];
vector<int> X[maxn]; vector<int> Y;
inline getid(int y){return lower_bound(Y.begin(),Y.end(),y)-Y.begin()+;}
inline getval(int id){return Y.at(id-);} struct _BIT
{
int N,C[maxn];
int lowbit(int x){return x&(-x);}
void init(int n)//初始化共有n个点
{
N=n;
for(int i=;i<=N;i++) C[i]=;
}
void update(int pos,int val)
{
while(pos<=N)
{
C[pos]=max(C[pos],val);
pos+=lowbit(pos);
}
}
int askmax(int pos)
{
int ret=;
while(pos>)
{
ret=max(ret,C[pos]);
pos-=lowbit(pos);
}
return ret;
}
}BIT; int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
Y.clear();
for(int i=;i<n;i++)
{
scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].v);
if(node[i].x== || node[i].y==) node[i].v=;
Y.push_back(node[i].y);
} sort(Y.begin(),Y.end());
Y.erase(unique(Y.begin(),Y.end()),Y.end()); sort(node,node+n,cmp); int tot=;
for(int i=;i<n;i++)
{
node[i].y = getid(node[i].y);
if(i== || node[i].x>node[i-].x)
{
tot++;
X[tot].clear();
}
X[tot].push_back(i);
} BIT.init(n);
int ans=;
for(int i=;i<=tot;i++)
{
int now;
for(int j=;j<X[i].size();j++)
{
now=X[i][j];
dp[now]=BIT.askmax(node[now].y-)+node[now].v;
ans=max(ans,dp[now]);
}
for(int j=;j<X[i].size();j++)
{
now=X[i][j];
BIT.update(node[now].y,dp[now]);
}
} cout<<ans<<endl;
}
}
附一个bin神的代码
#include <bits/stdc++.h>
using namespace std; struct Node {
int x, y, v;
void input() {
scanf("%d%d%d", &x ,&y, &v);
}
}node[];
bool cmp(Node a, Node b) {
return a.x < b.x;
} int a[];
int tot; int c[];
int lowbit(int x) {
return x&(-x);
} void update(int i, int val) {
while (i <= tot) {
c[i] = max(c[i], val);
i += lowbit(i);
}
}
int query(int i) {
int res = ;
while (i > ) {
res = max(res, c[i]);
i -= lowbit(i);
}
return res;
} int dp[]; int main() {
int T;
int n;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = ; i < n; i++)
node[i].input();
tot = ;
for (int i = ; i < n; i++) {
a[tot++] = node[i].y;
}
sort(a, a+tot);
tot = unique(a, a+tot) - a;
for (int i = ; i < n; i++) {
node[i].y = lower_bound(a, a+tot, node[i].y) - a + ;
}
sort(node, node+n, cmp);
for (int i = ; i < n; i++) dp[i] = node[i].v;
for (int i = ; i <= tot; i++) c[i] = ;
int pos = ;
int ans = ;
for (int i = ; i < n; i++) {
while (pos < i && node[pos].x < node[i].x) {
update(node[pos].y, dp[pos]);
pos++;
}
dp[i] = query(node[i].y - ) + node[i].v;
ans = max(ans, dp[i]);
}
printf("%d\n",ans);
}
return ;
}
非常简洁,空间消耗很少,%%%
HDU 6447 - YJJ's Salesman - [树状数组优化DP][2018CCPC网络选拔赛第10题]的更多相关文章
- HDU 6240 Server(2017 CCPC哈尔滨站 K题,01分数规划 + 树状数组优化DP)
题目链接 2017 CCPC Harbin Problem K 题意 给定若干物品,每个物品可以覆盖一个区间.现在要覆盖区间$[1, t]$. 求选出来的物品的$\frac{∑a_{i}}{∑b_ ...
- Codeforces 946G Almost Increasing Array (树状数组优化DP)
题目链接 Educational Codeforces Round 39 Problem G 题意 给定一个序列,求把他变成Almost Increasing Array需要改变的最小元素个数. ...
- LUOGU P2344 奶牛抗议 (树状数组优化dp)
传送门 解题思路 树状数组优化dp,f[i]表示前i个奶牛的分组的个数,那么很容易得出$f[i]=\sum\limits_{1\leq j\leq i}f[j-1]*(sum[i]\ge sum[j- ...
- 【题解】Music Festival(树状数组优化dp)
[题解]Music Festival(树状数组优化dp) Gym - 101908F 题意:有\(n\)种节目,每种节目有起始时间和结束时间和权值.同一时刻只能看一个节目(边界不算),在所有种类都看过 ...
- 【题解】ARC101F Robots and Exits(DP转格路+树状数组优化DP)
[题解]ARC101F Robots and Exits(DP转格路+树状数组优化DP) 先删去所有只能进入一个洞的机器人,这对答案没有贡献 考虑一个机器人只能进入两个洞,且真正的限制条件是操作的前缀 ...
- Codeforces 909C Python Indentation:树状数组优化dp
题目链接:http://codeforces.com/contest/909/problem/C 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现. 现在有一种简化版的Pytho ...
- BZOJ3594: [Scoi2014]方伯伯的玉米田【二维树状数组优化DP】
Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...
- Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)
题意: 线段树做法 分析: 因为每次都是在当前位置的前缀区间查询最大值,所以可以直接用树状数组优化.比线段树快了12ms~ 代码: #include<cstdio> #include< ...
- BZOJ 3594: [Scoi2014]方伯伯的玉米田 (二维树状数组优化DP)
分析 首先每次增加的区间一定是[i,n][i,n][i,n]的形式.因为如果选择[i,j](j<n)[i,j](j<n)[i,j](j<n)肯定不如把后面的全部一起加111更优. 那 ...
随机推荐
- 5 -- Hibernate的基本用法 --4 2 hibernate.properties文件与hibernate.cfg.xml文件
hibernate.properties : project\etc\hibernate.properties hibernate.cfg.xml : project\etc\hibernate.cf ...
- 【代码审计】iZhanCMS_v2.1 后台存在多个SQL注入漏洞分析
0x00 环境准备 iZhanCMS官网:http://www.izhancms.com 网站源码版本:爱站CMS(zend6.0) V2.1 程序源码下载:http://www.izhancms ...
- sqlserver添加查询 表、字段注释(转)
环境:xp sp3,sql server2008 .sqlserver用语句给表注释 EXECUTE sp_addextendedproperty N'MS_Description', N'表注释', ...
- strcat的几种实现及性能比较
一 原型说明 strcat()为C语言标准库函数,用于字符串拼接.函数原型声明在string.h头文件中: char *strcat(char *dest, const char *src); 该函 ...
- 为什么WAN口IP和外网IP不一样(不一致)?
正常的网络应该是动态公网ip,也就是路由器里面的WAN口IP与www.ip138.com上面显示的是一致的,不一致的话则说明该网络被电信或者联通做了NAT转发,导致您获取到了一个虚假的IP地址,无法用 ...
- elasticsearch基础----->elasticsearch环境的搭建
这里面我们主要是在ubuntu系统上对elasticsearch进行一个环境的搭建,记录一下这个过程中遇到的一些问题以及解决方案.我总是躲在梦与季节的深处,听花与黑夜唱尽梦魇,唱尽繁华,唱断所有记忆的 ...
- Twitter的SnowFlake分布式id生成算法
二进制相关知识回顾 1.所有的数据都是以二进制的形式存储在硬盘上.对于一个字节的8位到底是什么类型 计算机是如何分辨的呢? 其实计算机并不负责判断数据类型,数据类型是程序告诉计算机该如何解释内存块. ...
- js - 预加载+监听图片资源加载制作进度条
这两天遇到一个新需求:一个一镜到底的h5动画.因为功能的特殊性,就要求我们提前监听页面的静态图片是否全部加载完毕.即处理预加载. 总结下来,下次这种需求需要提前注意以下几点: 一.图片而不是背景图 本 ...
- smarty直接在模板中格式化时间的方法
smarty提供了一个获取时间戳的方法: <%$smarty.now%> 使用该方法获取到当时的时间戳之后,使用格式化修饰符data-format进行修饰: <%$smarty.no ...
- 深入学习Make命令和Makefile(上)
https://www.zybuluo.com/lishuhuakai/note/209302 深入学习Make命令和Makefile(上) make是Linux下的一款程序自动维护工具,配合make ...