POJ 2482 Stars in Your Window 线段树+离散化+扫描线

题面据说很美~

每个星星可以根据在窗口的左下角和右上角两个位置建立两条扫描线,之后就是简单的区间增减和求最大值操作了。

注意要处理在边界上的星星是不算的情况,其实只要把左右边界分别增减一个eps即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <bitset>
#include <list>
#include <cstdlib>
#include <climits>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <stack>
#include <sstream>
#include <numeric>
#include <fstream>
#include <functional>

using namespace std;

#define MP make_pair
#define PB push_back
#define lson rt << 1,l,mid
#define rson rt << 1 | 1,mid + 1,r
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef pair<int,int> pii;
const int INF = INT_MAX / 3;
const double eps = 1e-4;
const LL LINF = 1e17;
const double DINF = 1e60;
const int maxn = 1e5 + 5;

struct Seg {
    double x,l,r;
    int cover;
    Seg(double x,double l,double r,int cover): x(x),l(l),r(r),cover(cover) {}
    bool operator < (const Seg &s) const {
        return x < s.x;
    }
};

vector<Seg> s;
vector<double> numy;
LL lazy[maxn << 2],maxv[maxn << 2];
int W,H,n;

void add_line(int x,int y,int cover) {
    double x1 = x - W + eps, x2 = x - eps, y1 = y - H + eps, y2 = y - eps;
    s.PB(Seg(x1,y1,y2,cover));
    s.PB(Seg(x2,y1,y2,-cover));
    numy.PB(y1); numy.PB(y2);
}

int getID(double Val) {
    return lower_bound(numy.begin(),numy.end(),Val) - numy.begin();
}

void pushdown(int rt,int l,int r) {
    if(lazy[rt] == 0) return;
    int lc = rt << 1,rc = rt << 1 | 1;
    lazy[lc] += lazy[rt]; lazy[rc] += lazy[rt];
    maxv[lc] += lazy[rt]; maxv[rc] += lazy[rt];
    lazy[rt] = 0;
}

void pushup(int rt,int l,int r) {
    maxv[rt] = max(maxv[rt << 1] ,maxv[rt << 1 | 1]);
}

void update(int rt,int l,int r,int ql,int qr,int Val) {
    if(ql <= l && qr >= r) {
        lazy[rt] += Val;  maxv[rt] += Val;
    }
    else {
        pushdown(rt,l,r);
        int mid = (l + r) >> 1;
        if(ql <= mid) update(lson,ql,qr,Val);
        if(qr > mid) update(rson,ql,qr,Val);
        pushup(rt,l,r);
    }
}

void solve() {
    sort(numy.begin(),numy.end());
    sort(s.begin(),s.end());
    int ks = s.size(), ky = numy.size();
    LL ans = 0;
    for(int i = 0;i < ks;i++) {
        int ql = getID(s[i].l),qr = getID(s[i].r);
        update(1,0,ky - 1,ql,qr,s[i].cover);
        ans = max(ans,maxv[1]);
    }
    cout << ans << endl;
}

int main() {
    while(scanf("%d%d%d",&n,&W,&H) != EOF) {
        numy.clear(); s.clear();
        for(int i = 0;i < n;i++) {
            int x,y,cover; scanf("%d%d%d",&x,&y,&cover);
            add_line(x,y,cover);
        }
        solve();
    }
    return 0;
}

  

POJ 2482 Stars in Your Window 线段树+离散化+扫描线,布布扣,bubuko.com

时间: 2024-12-21 21:51:00

POJ 2482 Stars in Your Window 线段树+离散化+扫描线的相关文章

POJ 2482 stars in your window(线段树 , 扫描线)

题目大意: 给你10000以内的星星的坐标和亮度,让你用一个W × H 的矩形去围住一个区域,使得区域内星星的亮度最大,矩形边缘上的星星不算. 解题思路: 对于每一个星星 建立一个(x, y , y + h , c) 的扫描线 和一个(x + w , y , y + h , - c)的扫描线,将问题转化成求区间最大值.几个需要注意的地方:矩形边缘上的需要处理一下,将每个叶节点设为长度为1的线段.另外此题如果用long long wa掉的话可以改为unsigned. #include <iostr

POJ 2482 Stars in Your Window 线段树扫描线

Stars in Your Window Description Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw you? I still remember, vividly, on the beautiful Zhuhai Campus, 4 years ago, from the moment I saw you smile, as you were walkin

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

[POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11294   Accepted: 3091 Description Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw you? I still remembe

POJ 2482 Stars in Your Window(线段树)

POJ 2482 Stars in Your Window 题目链接 题意:给定一些星星,每个星星都有一个亮度,现在要用w * h的矩形去框星星,问最大能框的亮度是多少 思路:转化为扫描线的问题,每个星星转化为一个矩形,那么等于求矩形相交区域值最大的区域,利用线段树去维护即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long lo

poj 2482 Stars in Your Window(扫描线)

题目链接:poj 2482 Stars in Your Window 题目大意:平面上有N个星星,问一个W?H的矩形最多能括进多少个星星. 解题思路:扫描线的变形.只要以每个点为左上角,建立矩形,这个矩形即为框框左下角放的位置可以括到该点,那么N个星星就有N个矩形,扫描线处理哪些位置覆盖次数最多. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using

POJ 2482 Stars in Your Window

线段树+离散化+扫描线 AC之后,又认真读了一遍题目,好文章. #include<cstdio> #include<map> #include<algorithm> using namespace std; const int maxn=100000+10; int n; long long W,H; long long x[maxn],y[maxn],v[maxn]; struct seg { long long X; long long Y1,Y2; long lo

POJ - 2528 - Mayor&#39;s posters 【线段树+离散化+补点】

http://poj.org/problem?id=2528 #include <cstdio> #include <iostream> #include <set> #include <cstring> #include <string> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 32768 + 5; in

POJ 2528 Mayor&#39;s posters(线段树+离散化)

题目链接:Mayor's posters 题意:按顺序往墙上贴海报,可以重叠,问最后可以看到多少海报.(被覆盖的海报是看不到的) 注意: 因为数据比较大,所以不离散化,肯定爆内存. 还有就是,不能只是单纯的离散化,还要处理好点的边界 举个例子 4 2  10. 2  8 3  6 6  8 8  10 离散化后 2 3 6 8 10 1 2 3 4 5 覆盖掉了 1 5   和  1 4俩段 只剩下 2  3  .3  4. 4  5 答案是 3 但是正确答案是4 所以,离散化处理时要处理边界,

poj(2528)——Mayor&#39;s posters(线段树+离散化)

这道题目让我又重新认识了一下离散化: 首先总结一下离散化的特点: 1)有时区间的端点并不是整数,或者区间太大导致建树内存开销过大而MLE,那么就需要进行离散化后再建树. 2)意思是将区间范围很大的数据集映射到较小的数据集,这样建树更加有效,或者说我们只取需要的值来用. 这个意思说到底就是进行映射,把原来很大的映射到一个较小的空间中去. 题意: 给定一些海报,它们可能相互重叠,告诉你每个海报的宽度(它们的高度都是一样的)和先后的叠放次序,问没有被完全盖住的海报有多少张? 这里我们注意到了数据的范围