Description
给出二维平面上的nnn个不同的点(xi,yi)(x_i,y_i)(xi,yi),现在要从(0,0)(0,0)(0,0)走到(109,109)(10^9,10^9)(109,109),每次只能从(x,y)(x,y)(x,y)走到(x,y+1),(x+1,y),(x+1,y+1)(x,y+1),(x+1,y),(x+1,y+1)(x,y+1),(x+1,y),(x+1,y+1)中的一点,且如果是从(xk−1,yk−1)(x_k-1,y_k-1)(xk−1,yk−1)走到(xk,yk)(x_k,y_k)(xk,yk)的话,会收益vkv_kvk,问从(0,0)(0,0)(0,0)走到(109,109)(10^9,10^9)(109,109)的最大收益
Input
第一行一整数TTT表示用例组数,每组用例首先输入一整数nnn表示点数,之后nnn行每行输入三个整数xk,yk,vkx_k,y_k,v_kxk,yk,vk表示第kkk个点的坐标和价值
(1≤T≤10,1≤n≤105,0≤xk,yk≤109)(1\le T\le 10,1\le n\le 10^5,0\le x_k,y_k\le 10^9)(1≤T≤10,1≤n≤105,0≤xk,yk≤109)
Output
输出最大收益
Sample Input
1
3
1 1 1
1 2 2
3 3 1
Sample Output
3
Solution
把所有点按横坐标离散化为mmm列,以dp[i]dp[i]dp[i]表示从起点到第iii列的最大收益,把所有点按纵坐标排序,按横坐标离散化后的值转移即可,即对于当前点(x,y,v)(x,y,v)(x,y,v)(不妨认为xxx是离散化后的横坐标),有转移
dp[x]=max(dp[i],1≤i<x)+v
dp[x]=max(dp[i],1\le i<x)+v
dp[x]=max(dp[i],1≤i<x)+v
用BITBITBIT维护一下dpdpdp数组的前缀和最大值即可,时间复杂度O(nlogn)O(nlogn)O(nlogn)
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100005;
struct BIT
{
#define lowbit(x) (x&(-x))
int b[maxn],n;
void init(int _n)
{
n=_n;
for(int i=1;i<=n;i++)b[i]=0;
}
void update(int x,int v)
{
while(x<=n)
{
b[x]=max(b[x],v);
x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while(x)
{
ans=max(b[x],ans);
x-=lowbit(x);
}
return ans;
}
}bit;
struct node
{
int x,y,v;
bool operator<(const node &b)const
{
if(y!=b.y)return y<b.y;
return x>b.x;
}
}a[maxn];
int T,n,h[maxn],dp[maxn];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);
a[n+1].x=a[n+1].y=a[n+1].v=0;
a[n+2].x=a[n+2].y=1e9,a[n+2].v=0;
n+=2;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)h[i-1]=a[i].x;
sort(h,h+n);
int m=unique(h,h+n)-h;
for(int i=1;i<=n;i++)a[i].x=lower_bound(h,h+m,a[i].x)-h+1;
bit.init(m);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
int id=a[i].x;
dp[id]=max(dp[id],bit.query(id-1)+a[i].v);
bit.update(id,dp[id]);
}
int ans=0;
for(int i=1;i<=m;i++)ans=max(ans,dp[i]);
printf("%d\n",ans);
}
return 0;
}