您的位置:首页 > 其它

poj 2482 Stars in Your Window(线段树+离散化+线扫描)

2013-06-22 21:05 549 查看
题目:http://poj.org/problem?id=2482

大意:在一个坐标系中给你n(10^4)个点(点的坐标范围为0<=x,y<2^31),每个点有一个权值,然后给你一个长宽分别为w,h(10^6)的矩形(平行于坐标轴);
现在你的任务就是求出用这个矩形所覆盖的点的权值和的最大值(矩形边上的点不算)(矩形可以平移但是不能旋转)

思路:每个星星都可以以它自己为矩形的左下角(不能包括矩形边),那么就有n个矩形,就转化成了黑书上的第108页的题目,即统计所有1x1的小方格被覆盖的矩形最多的;

由于点的数量很小,但是坐标的范围很大,于是需要离散化;

  自左向右扫描,左右竖线(在程序中用正负表示)标志矩形进入和退出阴影区域,利用线段树进行更新;

代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10010;
struct node
{
__int64 id;//坐标值
int flag;//标记左边还是右边
int xh;//序号
}sx[maxn*2],sy[maxn*2];
struct bj
{
int y1,y2;
int val;//左进右出,左为正,有为负
}line[maxn*2];
int n;
int tree[maxn*8];
int lz[maxn*8];//懒惰标记
bool cmp(struct node a,struct node b)
{
if(a.id==b.id)
return a.flag>b.flag;
return a.id<b.id;
}
void disper()//离散化
{
sort(sx,sx+(n<<1),cmp);
sort(sy,sy+(n<<1),cmp);
int temp=sy[0].id;
int tg=1;
int i;
for(i=0;i<n*2;i++)
{
if(temp!=sy[i].id)
{
tg++;
temp=sy[i].id;
}
if(sy[i].flag)
{
line[sy[i].xh*2].y2=tg;
line[sy[i].xh*2+1].y2=tg;
}
else
{
line[sy[i].xh*2].y1=tg;
line[sy[i].xh*2+1].y1=tg;
}
}
}
void build(int l,int r,int w)
{
tree[w]=0;
lz[w]=0;
if(l==r)
{
return ;
}
int m=(l+r)>>1;
build(l,m,w<<1);
build(m+1,r,w<<1|1);
}

void update(int l,int r,int w,int L,int R,int val)
{
if(L<=l&&R>=r)
{
tree[w]+=val;
lz[w]+=val;//延迟标记
return ;
}
if(lz[w]!=0)//取消标记
{
lz[w<<1|1]+=lz[w];
lz[w<<1]+=lz[w];
tree[w<<1]+=lz[w];
tree[w<<1|1]+=lz[w];
lz[w]=0;
}
int m=(l+r)>>1;
if(L>m)
update(m+1,r,w<<1|1,L,R,val);
else if(R<=m)
update(l,m,w<<1,L,R,val);
else
{
update(l,m,w*2,L,m,val);
update(m+1,r,w<<1|1,m+1,R,val);
}
tree[w]=max(tree[w<<1],tree[w<<1|1]);
}
int main()
{
int w,h;
while(scanf("%d%d%d",&n,&w,&h)!=EOF)
{
int i;
__int64 x,y;
int valu;
for(i=0;i<n;i++)
{
scanf("%I64d%I64d%d",&x,&y,&valu);
sx[i<<1].id=x;
sx[i<<1].flag=0;//左边
sx[i<<1|1].id=x+w;
sx[i<<1|1].flag=1;//右边
sx[i<<1|1].xh=sx[i<<1].xh=i;

sy[i<<1].id=y;
sy[i<<1].flag=0;
sy[i<<1|1].id=y+h;
sy[i<<1|1].flag=1;
sy[i<<1|1].xh=sy[i<<1].xh=i;

line[i<<1].val=valu;
line[i<<1|1].val=-valu;
}
disper();//离散化
/*for(i=0;i<n*2;i++)
{
printf("%d %d %d\n",line[i].yd,line[i].yu,line[i].val);
}*/
n=n*2;
build(1,n,1);

int id;
int ans=0;
for(i=0;i<n;i++)//扫描
{
id=sx[i].xh*2+sx[i].flag;
line[id].y1++;//不包括边
update(1,n,1,line[id].y1,line[id].y2,line[id].val);
if(ans<tree[1])
ans=tree[1];
}
printf("%d\n",ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: