题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6447
因为图中点的坐标值过大,达到1e9.然而只有1e5个点。所以先将其离散化。并按照<x.y>二元组排序。每次对于同一行的点连续处理两次。
第一次:先考虑由上一行转移而来的情况:树状数组找到左上角的最大值+v、以及上方值的最大值。
第二次:考虑由同行的点转移来的情况。树状数组查询区间1~x-1的最大值
便利过程中维护最大值
代码丑的一批
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
#define sqr(a) a*a
using namespace std;
#define maxn 100010
int shu[maxn];
int lowbit(int i)
{
return i&(-i);
}
int query(int i)
{
int ans=0;
while(i)
{
ans=max(ans,shu[i]);
i-=lowbit(i);
}
return ans;
}
void update(int i,int p)
{
while(i<=maxn-1)
{
shu[i]=max(p,shu[i]);
i+=lowbit(i);
}
}
struct node
{
int x,y,v;
}a[100010];
int dp[100010];
int d[100010];
bool cmp(node a,node b)
{
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
bool cmp1(node a,node b)
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
lan(d,0);
lan(shu,0);
lan(a,0);
lan(dp,0);
int n;
scanf("%d",&n);
int x,y,v;
For(i,1,n)
{
scanf("%d%d%d",&x,&y,&v);
a[i].x=x;
a[i].y=y;
a[i].v=v;
}
sort(a+1,a+1+n,cmp1);
int tem=a[1].y;
int id=1;
a[1].y=1;
For(i,2,n)
{
if(a[i].y==tem)
{
a[i].y=id;
}
else
{
tem=a[i].y;
id++;
a[i].y=id;
}
}
sort(a+1,a+1+n,cmp);
tem=a[1].x;
id=1;
a[1].x=1;
d[1]=1;
For(i,2,n)
{
if(a[i].x==tem)
{
a[i].x=id;
d[id]++;
}
else
{
tem=a[i].x;
id++;
a[i].x=id;
d[id]++;
}
}
int maxx=0;
id=0;
int l=1,r;
For(i,1,n)
{
// printf("d[%d]=%d\n",i,d[i]);
if(!d[i])
continue;
For(j,1,d[i])
{
int k=j+id;
x=a[k].x;
y=a[k].y;
v=a[k].v;
int ans1=query(y-1)+v;
int ans2=query(y);
// printf("%d %d:%d %d\n",x,y,ans1,ans2);
dp[y]=max(ans1,ans2);
}
For(j,1,d[i])
{
int k=j+id;
x=a[k].x;
y=a[k].y;
v=a[k].v;
// printf("%d %d:%d\n",x,y,query(y-1));
maxx=max(maxx,max(dp[y],query(y-1)));
update(y,max(dp[y],query(y-1)));
}
id+=d[i];
}
printf("%d\n",maxx);
}
return 0;
}