【洛谷P1502】窗口的星星

好像跟POJ重题

这是一道扫描线的题。

由于窗口的大小已知,我们不妨换一下思路,把问题转化成这样:平面内有若干个矩形(大小就是窗口的大小,矩形左下角的位置就是某一颗星星的位置),每一个矩形覆盖的区域都有一个权值(星星的亮度),求某一位置,使得这个位置被覆盖的权值最大,最大值即答案。

为什么这样就是正确的?每一个窗口的大小都是固定的,假设我们把这个窗口的右上角放在刚刚所说的星星的矩形中,那么这颗星星一定能被看见。以此类推,假设我们把窗口的右上角放在尽可能多矩形的范围内(这里说的不太恰当,应该是放在权值加起来尽可能大的范围内),我们的答案就尽可能优,因此,我们只需要用扫描线求出最大的权值即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N=10010;
 7 int T;
 8 struct line {
 9     int x,y1,y2,v;
10     bool operator <(const line &xx) const {
11         if(x==xx.x) return v>xx.v;
12         return x<xx.x;
13     }
14 }a[N<<1];
15 int n,val[N<<1][2],raw[N<<1];
16 struct node {
17     int l,r;
18     int data,tag;
19 }s[N<<3];
20 int ans,t,w,h;
21 inline void build(int now,int l,int r) {
22     s[now].l=l;
23     s[now].r=r;
24     s[now].data=s[now].tag=0;
25     if(l==r) return ;
26     int mid=l+r>>1;
27     build(now<<1,l,mid);
28     build(now<<1|1,mid+1,r);
29 }
30 inline void pushdown(int now) {
31     if(s[now].tag) {
32         int v=s[now].tag;
33         s[now<<1].tag+=v;
34         s[now<<1|1].tag+=v;
35         s[now<<1].data+=v;
36         s[now<<1|1].data+=v;
37         s[now].tag=0;
38     }
39 }
40 void updata(int now,int l,int r,int v) {
41     if(l<=s[now].l&&s[now].r<=r) {
42         s[now].data+=v;
43         s[now].tag+=v;
44         return ;
45     }
46     pushdown(now);
47     int mid=s[now].l+s[now].r>>1;
48     if(l<=mid) updata(now<<1,l,r,v);
49     if(r>mid) updata(now<<1|1,l,r,v);
50     s[now].data=max(s[now<<1].data,s[now<<1|1].data);
51 }
52 int main() {
53     scanf("%d",&T);
54     while(T--) {
55         ans=t=0;
56         scanf("%d%d%d",&n,&w,&h);
57         for(int i=1;i<=n;i++) {
58             int x,y,z;
59             scanf("%d%d%d",&x,&y,&z);
60             a[2*i-1]=(line){x,y,y+h,z};
61             a[2*i]=(line){x+w-1,y,y+h,-z};
62             raw[++t]=y;
63             raw[++t]=y+h-1;
64         }
65         sort(a+1,a+2*n+1);
66         sort(raw+1,raw+t+1);
67         t=unique(raw+1,raw+t+1)-raw-1;
68         for(int i=1;i<=2*n;i++) {
69             val[i][0]=lower_bound(raw+1,raw+t+1,a[i].y1)-raw;
70             val[i][1]=lower_bound(raw+1,raw+t+1,a[i].y2)-raw;
71         }
72         build(1,1,t);
73         for(int i=1;i<=2*n;i++) {
74             updata(1,val[i][0],val[i][1]-1,a[i].v);
75             ans=max(ans,s[1].data);
76         }
77         printf("%d
",ans);
78     }
79     return 0;
80 }
AC Code
原文地址:https://www.cnblogs.com/shl-blog/p/10960214.html