2018 CCPC网络赛 1010 hdu 6447 ( 树状数组优化dp)

时间:2021-12-08 22:10:18

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

思路:很容易推得dp转移公式:dp[i][j] = max(dp[i][j-1],dp[i-1][j],dp[i-1][j-1]+val[i][j]) ,但是很明显离散化后也无法储存这些点,我们可以用树状数组对这个状态转移公式进行优化,我们先以y轴为第一优先级从小到大排序,以x轴为第二优先级从大到小排序,对x轴坐标进行离散化,这样我们就只需要维护x轴上的最大值即可,状态转移方程可优化为: dp[i] = max(dp[i],dp[k]+val) 其中 0<k<i,dp[k]表示dp[1]到dp[i-1]的最大值(可用树状数组维护)

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5+;
struct node{
int x,y,val;
bool operator < (const node &k)const{
if(y == k.y) return x > k.x;
return y < k.y;
}
}a[M];
int c[M],pos[M],n;
void add(int x,int val){
while(x <= n){
c[x] = max(c[x],val);
x += (x&-x);
}
} int getsum(int x){
int res = ;
while(x){
res = max(res,c[x]);
x -= (x&-x);
}
return res;
} int main(){
int t;
scanf("%d",&t);
while(t--){
memset(c,,sizeof(c));
scanf("%d",&n);
for(int i = ;i <= n;i ++){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);
pos[i] = a[i].x;
}
sort(a+,a++n); sort(pos+,pos++n);
int ans = ;
for(int i = ;i <= n;i ++){
int cnt = lower_bound(pos+,pos++n,a[i].x)-pos;
int num = a[i].val + getsum(cnt-);
ans = max(ans,num);
add(cnt,num);
}
printf("%d\n",ans);
}
}