hdu 5091 Beam Cannon

题目大意:

有n个点(n<=10000),点的坐标绝对值不超过20000,然后问你用一个w*h(1<=w,h<=40000)的矩形,矩形的边平行于坐标轴,最多能盖住多少个点。

刘汝佳黑书上有原题

下面这份代码是加了离散化的,用垂直于x轴的直线去扫描,在y轴上建立线段树,所以对于每一个点(x,y),赋予权值1,,然后增加一个新的负点(x+w,y),赋予权值-1。当扫描线扫过每一个点,用该点的权值去区间更新线段树。维护每个区间的sum值,因为是区间更新,所以还要打个lazy标记。

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<math.h>
  4 #include<string.h>
  5 #include<iostream>
  6 #include<string>
  7 #include<map>
  8 #include<set>
  9 #include<algorithm>
 10 #include<queue>
 11 #include<vector>
 12 #define N 40000
 13 using namespace std;
 14
 15 struct Node
 16 {
 17     int l,r,lazy;
 18     int sum;
 19 } node[N<<2];
 20 struct Line
 21 {
 22     int x,y1,y2,v;
 23     Line(){}
 24     Line(int a,int b,int c,int d)
 25     {
 26         x=a,y1=b,y2=c,v=d;
 27     }
 28     bool operator<(const Line&a)const
 29     {
 30         if(x==a.x)
 31             return v>a.v;
 32         return x<a.x;
 33     }
 34 } line[N];
 35 int lisan[N];
 36 int cnt=0;
 37 void pushup(int rt)
 38 {
 39     node[rt].sum=max(node[rt<<1].sum,node[rt<<1|1].sum);
 40 }
 41 void pushdown(int rt)
 42 {
 43     if(node[rt].lazy)
 44     {
 45         node[rt<<1].lazy+=node[rt].lazy;
 46         node[rt<<1|1].lazy+=node[rt].lazy;
 47         node[rt<<1].sum+=node[rt].lazy;
 48         node[rt<<1|1].sum+=node[rt].lazy;
 49         node[rt].lazy=0;
 50     }
 51 }
 52 void build(int rt,int l,int r)
 53 {
 54     node[rt].sum=0,node[rt].lazy=0;
 55     node[rt].l=l,node[rt].r=r;
 56     if(l==r)
 57         return;
 58     int mid=l+r>>1;
 59     build(rt<<1,l,mid);
 60     build(rt<<1|1,mid+1,r);
 61     pushup(rt);
 62 }
 63 void update(int rt,int l,int r,int v)
 64 {
 65     if(l<=node[rt].l&&node[rt].r<=r)
 66     {
 67         node[rt].lazy+=v;
 68         node[rt].sum+=v;
 69         return;
 70     }
 71     pushdown(rt);
 72     int mid=node[rt].l+node[rt].r>>1;
 73     if(l<=mid)
 74         update(rt<<1,l,r,v);
 75     if(r>mid)
 76         update(rt<<1|1,l,r,v);
 77     pushup(rt);
 78 }
 79 int query(int rt,int l,int r)
 80 {
 81     if(l<=node[rt].l&&node[rt].r<=r)
 82     {
 83         return node[rt].sum;
 84     }
 85     pushdown(rt);
 86     int mid=node[rt].l+node[rt].r>>1,ans=0;
 87     if(l<=mid)
 88         ans+=query(rt<<1,l,r);
 89     if(r>mid)
 90         ans+=query(rt<<1|1,l,r);
 91     return ans;
 92 }
 93 int main()
 94 {
 95     int n,w,h;
 96     while(scanf("%d",&n))
 97     {
 98         cnt=0;
 99         if(n<0)
100             break;
101         scanf("%d%d",&w,&h);
102         for(int i=0;i<n;++i)
103         {
104             int x,y;
105             scanf("%d%d",&x,&y);
106             x+=20001;
107             y+=20001;
108             lisan[cnt]=y;
109             line[cnt++]=Line(x,y,y+h,1);
110             lisan[cnt]=y+h;
111             line[cnt++]=Line(x+w,y,y+h,-1);
112         }
113         sort(line,line+cnt);
114         sort(lisan,lisan+cnt);
115         int num=unique(lisan,lisan+cnt)-lisan;
116         build(1,0,num-1);
117         int ans=0;
118         for(int i=0;i<cnt;++i)
119         {
120             int l=lower_bound(lisan,lisan+num,line[i].y1)-lisan;
121             int r=lower_bound(lisan,lisan+num,line[i].y2)-lisan;
122             update(1,l,r,line[i].v);
123             ans=max(ans,node[1].sum);
124         }
125         printf("%d\n",ans);
126     }
127
128 }
时间: 2024-10-12 17:40:08

hdu 5091 Beam Cannon的相关文章

hdu 5091 Beam Cannon(线段树扫描线)

题目链接:hdu 5091 Beam Cannon 题目大意:给定N个点,现在要有一个W?H的矩形,问说最多能圈住多少个点. 解题思路:线段的扫描线,假设有点(x,y),那么(x,y)~(x+W,y+H)形成的矩形,以框的右下角落的位置是可以圈住(x,y) 点,所以N个点即为N个矩形,求覆盖的最大次数,扫描线裸题. #include <cstdio> #include <cstring> #include <vector> #include <algorithm&

hdu 5091 Beam Cannon 离散化+扫描线+线段树

Beam Cannon Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 551    Accepted Submission(s): 207 Problem Description Recently, the γ galaxies broke out Star Wars. Each planet is warring for resou

hdu 5091 Beam Cannon(线段树+扫描线+离散化)

Beam Cannon Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 457    Accepted Submission(s): 175 Problem Description Recently, the γ galaxies broke out Star Wars. Each planet is warring for resou

线段树+扫描线 HDOJ 5091 Beam Cannon

题目传送门 1 /* 2 题意:给出若干个点的坐标,用一个矩形去覆盖,问最多能覆盖几个点 3 线段树+扫描线:思路是先建一棵以[y, y + h]的树,左右儿子[x, x + w] 4 以这棵树为范围,从左到右扫描,更新点数,x的+1, x+w的-1(超过矩形范围) 5 ans = 每次更新时所覆盖点数的最大值 6 */ 7 #include <cstdio> 8 #include <algorithm> 9 #include <iostream> 10 #includ

HDOJ 5091 Beam Cannon 扫描线

线段树+扫描线: 我们用矩形的中心点来描述这个矩形,然后对于每个敌舰,我们建立一个矩形中心的活动范围,即矩形中心在该范围内活动就可以覆盖到该敌舰.那么我们要求的问题就变成了:任意一个区域(肯定也是矩形的)最多能被矩形覆盖的最大值. Beam Cannon Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 159    Accepted S

[POI 2001+2014acm上海邀请赛]Gold Mine/Beam Cannon 线段树+扫描线

Description Byteman, one of the most deserving employee of The Goldmine of Byteland, is about to retire by the end of the year. The Goldmine management would like to reward him in acknowledgment of his conscientious work. As a reward Byteman may rece

【HDU 5091】Beam Cannon(扫描线)

按照x轴建树,求线段树的区间最值. 模型转化就是: 矩阵最大交 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define lson (pos<<1) #define rson (pos<<1|1) const int ADD = 25555; const int maxn = 80005; int n,w,h,cnt; struct Se

HDU 5091 线段树扫描线

给出N个点,和一个w*h的矩形 给出N个点的坐标,求该矩形最多可以覆盖多少个点 对每个点point(x,y)右边生成对应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍,遇到点则用该点的权值更新区间(y,y+h) #include "stdio.h" #include "string.h" #include "algorithm" using namespace std; struct Mark { int x,y,s; }ma

[线段树]HDU5091 Beam Cannon

题意:给n, w, h  (1 < = N < = 10000, 1 < = W < = 40000, 1 < = H < = 40000) w*h是可以射到的范围 然后给n个点的坐标x, y (-20000 < = x,y < = 20000) 问 射一次 能射到几个点. 很裸的扫描线线段树 这么水的题不知为何在现场没有写啊?????? 1 #include <cstdio> 2 #include <cstdlib> 3 #incl