poj2029和这道题差不多,也可以采用离散树,只不过比这个简单多啦,不用离散化的!
题目大意:给定一个矩形区域,其中矩形可以平移但是不可以旋转,和星星的位置以及权值,求就矩形放在哪里使得矩形内的星星的总权值最大,其中不包括矩形的边框区域!
解题思路:对于一个星星的表示:x,y,val。我们可以在x,x+w,处加一个星星,其中它的权值为-val,以便于当我们在扫描的时候扫到超过这个星星的横坐标矩形区域时可以进行自行的加减使得将这个星星的权值给约掉!
对于y轴可以建立线段树,因为数值较大星星的数目不多,所以要进行离散化的,对于每一个星星的加入都要对树进行更新,然后记录最大值,最后求得最大值就好了!
下面是代码,看了别人的n个题解啊,不过还好是看懂了。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
using namespace std;
#define ll __int64
#define rep(i,n) for(i=0; i<(n); i++)
#define reph(i,n,m) for(i=(n); i<=(m); i++)//正循环的
#define repd(i,n,m) for(i=(n); i>=(m); i--) //负循环的
#define fab(a) (a)>0?(a):0-(a)
#define arc(a) (a)*(a)
#define inf 10000000 //最大值的
#define exp 0.0000001 //浮点型的
#define N 10003
struct node
{
ll x,y,val;
}rr;
struct tree
{
int l,r;
ll Max,sum;
}rr1;
node li[N*2];
tree a[N*15];
ll rcy[N];
ll add;
int cmp(const void *a,const void *b)
{
node *c=(node *)a;
node *d=(node *)b;
if(c->x==d->x)
return c->val-d->val;
else
return c->x-d->x;
}
int cmp1(const void *a,const void *b)
{
return *(ll *)a-*(ll *)b;
}
void Maketree(int i,int l,int r)
{
a[i].Max=a[i].sum=0;
if(l==r)
return;
int mid=(l+r)/2;
Maketree(2*i,l,mid);
Maketree(2*i+1,mid+1,r);
}
void update(ll L,ll R,int l,int r,int i)
{
if(L<=rcy[l] && R>=rcy[r])
{
a[i].Max+=add;
a[i].sum+=add;
return ;
}
if(l==r)
return ;
if(a[i].sum)//不为0,即之前有覆盖的点但是没有分到子树上的
{
a[2*i].sum+=a[i].sum;
a[2*i].Max+=a[i].sum;
a[2*i+1].Max+=a[i].sum;
a[2*i+1].sum+=a[i].sum;
a[i].sum=0;
}
int mid=(l+r)/2;
if(L<=rcy[mid])
update(L,R,l,mid,2*i);
if(R>rcy[mid])
update(L,R,mid+1,r,2*i+1);
a[i].Max=max(a[2*i].Max,a[2*i+1].Max);//根的最大值只能是子女中的最大数的
}
int main()
{
int n,i,j,k;
ll w,h;
ll ans;
while(scanf("%d%I64d%I64d",&n,&w,&h)!=EOF)
{
reph(i,1,n)
{
scanf("%I64d%I64d%I64d",&li[i].x,&li[i].y,&li[i].val);
j=i+n;//增加点是为了进行约束的
rcy[i]=li[i].y;
li[j].x=li[i].x+w;
li[j].y=li[i].y;
li[j].val=-li[i].val;
}
k=n*2;
qsort(&li[1],k,sizeof(node),cmp);//x从大到小价值从高到低的
qsort(&rcy[1],n,sizeof(ll),cmp1);//对y值进行离散化的
for(i=2,j=1; i<=n; i++)//离散化的
if(rcy[i]!=rcy[j])//去除相同的啊
rcy[++j]=rcy[i];
n=j;ans=0;
Maketree(1,1,n);//根据y来建立的树的
reph(i,1,k)
{
add=li[i].val;
update(li[i].y,li[i].y+h-1,1,n,1);
ans=max(ans,a[1].Max);
}
printf("%I64d\n",ans);
}
return 0;
}