HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp
Posted cwolf9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp相关的知识,希望对你有一定的参考价值。
目录
(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
Catalog
Problem:Portal传送门
?原题目描述在最下面。
?1e5个点,问从(0,0)走到(1e9,1e9)的最大收益。
?当你从(u-1,v-1)走到(u,v)时,你可以获得点(u,v)的权值。
Solution:
?十分详细了。
?直接线段树区间最值。当然也可以树状数组,不能st表。
?(dp[i] = max(query\_max(0,dp[i]-1,1)+val[i] ,dp[i]))
?(update(i, dp[i],1))
?记得离散化再排序,先x从小到大,再y从大到小,每次更行一行。
?按01背包的更新顺序,滚动数组优化为一维。
?细节见代码。
AC_Code:
#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define mme(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef unsigned long long LL;
const int N = 2e5 + 7;
const int M = 1e5 + 7;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int ar[N],br[N];//离散化
int dp[N];
struct lh{//储存1e5个点
int x,y,v;
}op[N];
bool cmp(lh &a,lh &b){
if(a.x!=b.x)return a.x<b.x;
return a.y>b.y;
}
int n;
/**********线段树区间最值**********/
struct lp{
int l, r, sum;
}cw[N<<2];
void push_up(int rt){
cw[rt].sum = max(cw[lson].sum, cw[rson].sum);
}
void build(int l,int r,int rt){
cw[rt].l = l;cw[rt].r = r;cw[rt].sum = 0;
if(l==r){
return;
}
int mid = (l+r)/2;
build(l,mid,lson);build(mid+1,r,rson);
push_up(rt);
}
void update(int p,int c,int rt){
int l = cw[rt].l, r = cw[rt].r,mid = (l+r)/2;
if(l==r){
cw[rt].sum = c;
return;
}
if(p<=mid)update(p,c,lson);
else update(p,c,rson);
push_up(rt);
}
int query(int L,int R,int rt){
int l = cw[rt].l, r = cw[rt].r,mid = (l+r)/2;
if(L<=l&&r<=R){
return cw[rt].sum;
}
if(L>mid)return query(L,R,rson);
else if(R<=mid)return query(L,R,lson);
return max(query(L,mid,lson),query(mid+1,R,rson));
}
/****************/
int main(){
int tim;
scanf("%d", &tim);
while(tim--){
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d%d%d",&op[i].x,&op[i].y,&op[i].v);
ar[i] = op[i].x;br[i]=op[i].y;
}
int p = n + 1;
ar[n] = 0;br[n] = 0;
sort(ar,ar+p);
sort(br,br+p);
int a = unique(ar,ar+p)-ar;
int b = unique(br,br+p)-br;
for(int i = 0; i < n; ++i){
op[i].x=lower_bound(ar,ar+a,op[i].x)-ar;
op[i].y=lower_bound(br,br+b,op[i].y)-br;
}
//以上离散化
sort(op,op+n,cmp);
build(0, b, 1);
mme(dp, 0);
for(int i = 0; i < n; ++i){
int flag = op[i].x, j;
for(j = i; j < n; ++j){
if(op[j].x != flag){
break;
}
int tmp = query(0, op[j].y-1, 1) + op[j].v;
if(tmp > dp[op[j].y]){
dp[op[j].y] = tmp;
update(op[j].y, dp[op[j].y], 1);
}
}
i = j - 1;
}
int ans = 0;
for(int i = 0; i <= b; ++i){
ans = max(ans, dp[i]);
}
printf("%d
", ans);
}
return 0;
}
Problem Description:
以上是关于HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp的主要内容,如果未能解决你的问题,请参考以下文章
[HDU 6447][YJJ's Salesman][2018CCPC网络选拔赛 1010][离散化+线段树+DP]
HDU6447 YJJ's Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP
HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp