HUD 6447 YJJ's Salesman (dp + 樹狀陣列優化)
阿新 • • 發佈:2018-11-04
題意
給你一張
的地圖,你在
位置,你只能向右或者向下或者像右下走,之後給你一些點,你如果從右下走到這些點的時候就會得到他們的值(向右走或者向下走到這些點不會得到他們的值),現在問你如何走完全圖讓他們的權值最大。
思路
我們可以想到沒必要把所有的地圖的走完,我們只想著如何把這些有值的點全部都走完之後得到一個最大值就行,具體怎麼走呢?可以很顯然的得到,如果有兩個點A,B(B在A的右下角)倘若這兩個點不在同一行或者同一列,那麼我們一定能由A走到B的左上角一格C,之後由C 斜著走到B得到B點的權值,反之則不行,想到這點我們就可以想到這是一個一維的dp了,首先按照
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct node
{
int x,y,w;
friend bool operator < (const node &a,const node &b)
{
if(a.x == b.x) return a.y > b.y;
return a.x < b.x;
}
}edg[maxn];
int H[maxn] , T[maxn] , n;
void update(int pos,int v)
{
for(int i = pos ; i < (1 << 17) ; i += i&-i) T[i] = max(T[i],v);
}
int query(int pos)
{
int ans = 0;
for(int i = pos ; i ; i -= i&-i) ans = max(ans,T[i]);
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int tot = 0;
scanf("%d",&n);
memset(T,0,sizeof(T));
for(int i = 0 ; i < n ; i++)
{
scanf("%d%d%d",&edg[i].x,&edg[i].y,&edg[i].w);
H[tot++] = edg[i].y;
}
sort(edg,edg+n);
sort(H,H+tot);
tot = unique(H,H+tot) - H;
int ans = 0;
for(int i = 0 ; i < n ; i++)
{
int pos = lower_bound(H,H+tot,edg[i].y) - H + 1;
int te = query(pos-1) + edg[i].w;
update(pos,te);
ans = max(ans,te);
}
printf("%d\n",ans);
}
}