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

题目:http://poj.org/problem?id=2482

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

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

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

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

代码:

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn=10010;
  7 struct node
  8 {
  9     __int64 id;//坐标值
 10     int flag;//标记左边还是右边
 11     int xh;//序号
 12 }sx[maxn*2],sy[maxn*2];
 13 struct bj
 14 {
 15     int y1,y2;
 16     int val;//左进右出,左为正,有为负
 17 }line[maxn*2];
 18 int n;
 19 int tree[maxn*8];
 20 int lz[maxn*8];//懒惰标记
 21 bool cmp(struct node a,struct node b)
 22 {
 23     if(a.id==b.id)
 24     return a.flag>b.flag;
 25     return a.id<b.id;
 26 }
 27 void disper()//离散化
 28 {
 29     sort(sx,sx+(n<<1),cmp);
 30     sort(sy,sy+(n<<1),cmp);
 31     int temp=sy[0].id;
 32     int tg=1;
 33     int i;
 34     for(i=0;i<n*2;i++)
 35     {
 36         if(temp!=sy[i].id)
 37         {
 38             tg++;
 39             temp=sy[i].id;
 40         }
 41         if(sy[i].flag)
 42         {
 43             line[sy[i].xh*2].y2=tg;
 44             line[sy[i].xh*2+1].y2=tg;
 45         }
 46         else
 47         {
 48             line[sy[i].xh*2].y1=tg;
 49             line[sy[i].xh*2+1].y1=tg;
 50         }
 51     }
 52 }
 53 void build(int l,int r,int w)
 54 {
 55     tree[w]=0;
 56     lz[w]=0;
 57     if(l==r)
 58     {
 59         return ;
 60     }
 61     int m=(l+r)>>1;
 62     build(l,m,w<<1);
 63     build(m+1,r,w<<1|1);
 64 }
 65 
 66 void update(int l,int r,int w,int L,int R,int val)
 67 {
 68     if(L<=l&&R>=r)
 69     {
 70         tree[w]+=val;
 71         lz[w]+=val;//延迟标记
 72         return ;
 73     }
 74     if(lz[w]!=0)//取消标记
 75     {
 76         lz[w<<1|1]+=lz[w];
 77         lz[w<<1]+=lz[w];
 78         tree[w<<1]+=lz[w];
 79         tree[w<<1|1]+=lz[w];
 80         lz[w]=0;
 81     }
 82     int m=(l+r)>>1;
 83     if(L>m)
 84     update(m+1,r,w<<1|1,L,R,val);
 85     else if(R<=m)
 86     update(l,m,w<<1,L,R,val);
 87     else
 88     {
 89         update(l,m,w*2,L,m,val);
 90         update(m+1,r,w<<1|1,m+1,R,val);
 91     }
 92     tree[w]=max(tree[w<<1],tree[w<<1|1]);
 93 }
 94 int main()
 95 {
 96     int w,h;
 97     while(scanf("%d%d%d",&n,&w,&h)!=EOF)
 98     {
 99         int i;
100         __int64 x,y;
101         int valu;
102         for(i=0;i<n;i++)
103         {
104             scanf("%I64d%I64d%d",&x,&y,&valu);
105             sx[i<<1].id=x;
106             sx[i<<1].flag=0;//左边
107             sx[i<<1|1].id=x+w;
108             sx[i<<1|1].flag=1;//右边
109             sx[i<<1|1].xh=sx[i<<1].xh=i;
110 
111             sy[i<<1].id=y;
112             sy[i<<1].flag=0;
113             sy[i<<1|1].id=y+h;
114             sy[i<<1|1].flag=1;
115             sy[i<<1|1].xh=sy[i<<1].xh=i;
116 
117             line[i<<1].val=valu;
118             line[i<<1|1].val=-valu;
119         }
120         disper();//离散化
121         /*for(i=0;i<n*2;i++)
122         {
123             printf("%d %d %d\n",line[i].yd,line[i].yu,line[i].val);
124         }*/
125         n=n*2;
126         build(1,n,1);
127 
128         int id;
129         int ans=0;
130         for(i=0;i<n;i++)//扫描
131         {
132             id=sx[i].xh*2+sx[i].flag;
133             line[id].y1++;//不包括边
134             update(1,n,1,line[id].y1,line[id].y2,line[id].val);
135             if(ans<tree[1])
136             ans=tree[1];
137         }
138         printf("%d\n",ans);
139     }
140     return 0;
141 }
View Code

 

posted @ 2013-06-22 21:05  琳&leen  阅读(277)  评论(0编辑  收藏  举报