Poj--2482(线段树,扫描线,离散化)

2014-09-29 23:23:37

思路:这题RE到死啊!注意边界和long long!首先,考虑如果一个窗户套住了几个星星,那么可以移动窗户的左下角和最左下角的星星重合而使得套住的星星数不减。

那么就以每个星星为矩形的左下角,向右上拓展成一个矩形。那么如何转化为线段树呢?方法:先把所有星星按照y轴坐标升序排序,考虑每个星星的矩形的下底,一条线段,加入线段树中。即:从下往上扫,每遇到一条矩形下底,就将其加入线段树中,而且在加完后删除掉所有y轴坐标离当前星星y轴坐标>=H的星星下底(因为dis >= H的话就不能在一个窗户中了)

,然后每次还要根据当前最优解来更新答案。参考:http://www.cnblogs.com/wuyiqi/archive/2012/02/10/2346148.html

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <queue>
 7 #include <iostream>
 8 #include <algorithm>
 9 using namespace std;
10 #define lpos (pos << 1)
11 #define rpos (pos << 1|1)
12 #define getmid(l,r) (l + (r - l) / 2)
13 typedef long long ll;
14 const int INF = 1 << 29;
15 const int maxn = 20010;
16 
17 ll n,W,H;
18 
19 struct node{
20     ll cover;
21     ll tmax;
22 }t[maxn << 2];
23 
24 struct star{
25     ll x,y,c;
26 }s[maxn];
27 
28 ll x[maxn];
29 
30 void Push_down(ll pos){
31     ll vc = t[pos].cover;
32     ll vm = t[pos].tmax;
33     if(vc){
34         t[lpos].cover += vc;
35         t[rpos].cover += vc;
36         t[lpos].tmax += vc;
37         t[rpos].tmax += vc;
38         t[pos].cover = 0;
39     }
40 }
41 
42 void Update(ll a,ll b,ll c,ll pos,ll l,ll r){
43     if(a <= l && r <= b){
44         t[pos].cover += c;
45         t[pos].tmax += c;
46         return;
47     }
48     Push_down(pos);
49     ll mid = getmid(l,r);
50     if(a <= mid) Update(a,b,c,lpos,l,mid);
51     if(b > mid) Update(a,b,c,rpos,mid + 1,r);
52     t[pos].tmax = max(t[lpos].tmax,t[rpos].tmax);
53 }
54 
55 bool cmp(star a,star b){
56     return a.y < b.y;
57 }
58 
59 int main(){
60     ll cnt;
61     while(scanf("%I64d%I64d%I64d",&n,&W,&H) != EOF){
62         cnt = 0;
63         memset(t,0,sizeof(t));
64         for(ll i = 1; i <= n; ++i){
65             scanf("%I64d%I64d%I64d",&s[i].x,&s[i].y,&s[i].c);
66             x[++cnt] = s[i].x;
67             x[++cnt] = s[i].x + W;
68         }
69         sort(x + 1,x + cnt + 1);
70         sort(s + 1,s + n + 1,cmp);
71         ll sz = unique(x + 1,x + cnt + 1) - x - 1;
72         ll ans = 0,a,b;
73         for(ll i = 1,j = 1; i <= n; ++i){
74             a = lower_bound(x + 1,x + sz + 1,s[i].x) - x;
75             b = lower_bound(x + 1,x + sz + 1,s[i].x + W) - x - 1;
76             Update(a,b,s[i].c,1,1,sz);
77             while(j <= i && s[i].y - s[j].y >= H){
78                 a = lower_bound(x + 1,x + sz + 1,s[j].x) - x;
79                 b = lower_bound(x + 1,x + sz + 1,s[j].x + W) - x - 1;
80                 Update(a,b,-s[j].c,1,1,sz );
81                 ++j;
82             }
83             if(t[1].tmax > ans) ans = t[1].tmax;
84         }
85         printf("%I64d\n",ans);
86     }
87     return 0;
88 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4001164.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值