POJ_2482_Stars in Your Window_线段树、离散化处理
2015-05-04 13:29
549 查看
手机屏摔碎了哦凑。
题意
一个平面里有N(N<10000)个点,每个点 有一个值Vi,用一个长宽为W,H的矩形框,在平面内平移,不能旋转,最多能使框内(不包括边界)的点的V值和为多少 ?IO
InputThere are several test cases in the input. The first line of each case contains 3 integers: n, W, H, indicating the number of stars, the horizontal length and the vertical height of the rectangle-shaped window. Then n lines follow, with 3 integers each: x, y, c, telling the location (x, y) and the brightness of each star. No two stars are on the same point.
There are at least 1 and at most 10000 stars in the sky. 1<=W,H<=1000000, 0<=x,y<2^31.
Output
For each test case, output the maximum brightness in a single line.
分析
首先要对问题进行一次转化,对每个点来说,矩形框中心的位置必须在以当前点为中心的一个w,h的矩形框内,那么我们就可以把点转化为矩形,而把矩形转化为点。之所以要进行这样的转化,是因为我们要移动矩形,而点是不动的,显然矩形这一模型比点要复杂,因此我们把静态的点转化为更复杂的矩形,而把动态的矩形转化为简单的点。
用一条扫描线的从左往右扫,维护沿y轴方向矩形数量的分布信息,注意对于转化后的问题,扫描线进入一个矩形以后,分布信息中就应在对应位置加上它,知道出这个矩形,删除对应信息。用线段树来维护当前沿y轴矩形数量分布信息。
实现会遇到一些小问题:
从左到右的距离太大——排序矩形的左右边,扫描矩形左右边。
纵向距离太大——离散化纵向坐标。
按照题意点在框上的情况不算——由于输入都是整数,用一个小于0.5的小数修正即可。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define MXN 10010 int ll[MXN<<4],rr[MXN<<4],sum[MXN<<4],flag[MXN<<4]; int n,w,h; int ans; void build(int id,int l,int r){ ll[id]=l,rr[id]=r,sum[id]=flag[id]=0; int m=(l+r)>>1,ls=id<<1,rs=ls|1; if(l!=r){ build(ls,l,m); build(rs,m+1,r); } } struct line{ double x,l,h,v; bool end; line(){} line(double a,double b,double c,long long e,bool d){x=a,l=b,h=c,end=d,v=e;} bool operator < (const line& rgt)const{ return x<rgt.x||x==rgt.x&&end; } }l[MXN<<2]; long long lcnt,tot; double dy[MXN<<2]; void input(){ ans=lcnt=tot=0; for(int i=0;i<n;++i){ int tx,ty,tc; scanf("%d%d%d",&tx,&ty,&tc); double tl=ty-h/2.0+0.1; double th=ty+h/2.0-0.1; double ttx=tx-w/2.0+0.1; l[lcnt++]=line(ttx,tl,th,tc,false); ttx=tx+w/2.0-0.1; l[lcnt++]=line(ttx,tl,th,tc,true); dy[tot++]=tl; dy[tot++]=th; } sort(l,l+lcnt); sort(dy,dy+tot); tot=unique(dy,dy+tot)-dy; } void down(int id); void add(int id,double l,double r,int v,bool end){ if(flag[id]) down(id); if(l==dy[ll[id]]&&r==dy[rr[id]]){ flag[id]+=end ? -v : v; sum[id]+=flag[id]; return; } int m=(ll[id]+rr[id])>>1,ls=id<<1,rs=ls|1; if(r<=dy[m]) add(ls,l,r,v,end); else if(l>dy[m]) add(rs,l,r,v,end); else{ add(ls,l,dy[m],v,end); add(rs,dy[m+1],r,v,end); } sum[id]=max(sum[ls],sum[rs]); } void down(int id){ if(ll[id]==rr[id]){ flag[id]=0; return; } int m=(ll[id]+rr[id])>>1,ls=id<<1,rs=ls|1; add(ls,dy[ll[id]],dy[m],abs(flag[id]),flag[id]<0); add(rs,dy[m+1],dy[rr[id]],abs(flag[id]),flag[id]<0); flag[id]=0; } int query(int id){ if(flag[id]){ down(id); } return sum[id]; } void solve(){ for(int i=0;i<lcnt;++i){ add(1,l[i].l,l[i].h,l[i].v,l[i].end); ans=max(query(1),ans); } } int main(){ //freopen("data.txt","r",stdin); //freopen("ans.txt","w",stdout); while(scanf("%d%d%d",&n,&w,&h)!=EOF){ input(); build(1,0,tot-1); solve(); printf("%d\n",ans); } return 0; }
相关文章推荐
- POJ 题目2482 Stars in Your Window(线段树+离散化)
- POJ 2482 Stars in Your Window【离散化+扫描线+线段树
- poj2482 Stars in Your Window(线段树+扫描线+离散化)
- poj 2482 Stars in Your Window(线段树+扫描线+离散化)
- POJ 2482 Stars in Your Window(离散化+线段树:扫描线)
- poj 2482 Stars in Your Window(线段树+离散化+线扫描)
- POJ 2482 Stars in Your Window 离散化+扫描法 线段树应用
- poj 2482 Stars in Your Window 线段树 扫描线
- POJ 2482 Stars in Your Window(扫描线 + 线段树 区域统计)
- POJ-2482-Stars in Your Window(线段树,扫描线)
- POJ 2482 Stars in Your Window 线段树+离散化+扫描线
- POJ 2482 stars in your window(线段树 , 扫描线)
- poj 2482 Stars in Your Window 线段树
- POJ 2482 Stars in Your Window 线段树
- POJ 2482 Stars in Your Window(扫描线+线段树)
- poj-2482-Stars in Your Window-线段树
- POJ 2482 Stars in Your Window(线段树)
- poj 2482 Stars in Your Window 线段树
- poj 2482 Stars in Your Window(线段树,扫描线)
- 【POJ 2482】Stars in Your Window(扫描线+线段树)