题目链接:http://acm.nefu.edu.cn/JudgeOnline/forumDiscuss.php?problem_id=1485
这题和HDU那题没有什么区别,除了改了一点题意和数据比较水,我用一个排序和两个循环就解决了(我自己都不相信自己能过)
后来看这题真复杂,临时学了离散化和线段树才看懂题解
首先是离散化,是将数据大并且分散的连续数组变成连续的数组,比如说1 100 205 1005离散化就变成1 2 3 4
线段树是典型的二叉树,和树状数组一样是维护和查找的数组
上代码吧:
#include <iostream>
#include <string.h>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <stack>
#include <queue>
#include <sstream>
#include <vector>
#include <set>
using namespace std;
const int maxn=100005;
struct lattic
{
int x,y,w;
}a[maxn];
int b[maxn],sum[maxn*4];
int cmp(struct lattic x,struct lattic y)
{
if(x.x!=y.x)
return x.x<y.x;
else
return x.y>y.y;
}
int update(int k,int l,int r,int x,int w)
{
if(x<l||x>r)
return 0;
if(l==r&&l==x)
{
sum[k]=max(sum[k],w);
return 0;
}
int mid=(l+r)/2;
update(2*k,l,mid,x,w);
update(2*k+1,mid+1,r,x,w);
sum[k]=max(sum[2*k],sum[2*k+1]);
return 0;
}
int find(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
return sum[k];
int mid=(l+r)/2;
int ans=0;
if(x<=mid)
ans=find(2*k,l,mid,x,y);
if(y>mid)
ans=max(ans,find(2*k+1,mid+1,r,x,y));
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
b[i]=a[i].y;
}
sort(b+1,b+n+1);//先顺序化
int m=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)
a[i].y=lower_bound(b+1,b+1+m,a[i].y)-b;
sort(a+1,a+n+1,cmp);//完成离散化
for(int i=1;i<=n;i++)
{
if(a[i].y==1)//第一个不用查找
{
update(1,1,n,1,a[i].w);
}
else
{
int tmp=find(1,1,n,1,a[i].y-1);//找到的是在1到a[i].y-1中的最大的w
update(1,1,n,a[i].y,tmp+a[i].w);//将线段树更新
}
}
int ans=find(1,1,n,1,n);
printf("%d\n",ans);
}
return 0;
}