• P1502 | ACWing 248 窗口的星星


    题意简述

    现在有有(n)颗星星,第(i)颗星星可以用三元组((x_i,y_i,l_i))表示,意思是这颗星星在((x_i,y_i))处,亮度为(l_i)。现在有一个(w imes h)的窗户,找一个合适的位置放置这个窗户,使其圈起来的星星亮度和最大。边框位置不算。
    多组数据,(T le 10,n le 10^4,W,H le 10^6,0 le x_i,y_i le 2^{31})

    简单口胡

    容易发现如果确定矩形的右上角的位置,那么这个矩形就是确定的。
    于是我们考虑:
    将每个星星作为左下角画一个(W imes H)的矩形,任何在这个矩形里的点,将其作为窗户的右上角来画窗户,则这个窗户一定能框这颗星星。
    考虑到边界问题,我们将每颗星星向左下移动一格。用扫描线,将下底的权值设为(l_i),上底设为(-l_i),其实这里的“上底”应该是原来的上底再往上一个,因为处理完之后边界是可以停留的,所以应该再往上一个再减。
    然后我们维护中间的最大值即可。

    # include <bits/stdc++.h>
    using namespace std;
    const int N = 2e4 + 5;
    
    # define int long long
    int Test;
    int n,w,h;
    
    struct Star
    {
        int x,y;
        int l;
        Star() {}
        Star(int _x,int _y,int _l) : x(_x),y(_y),l(_l) {}
    }a[N << 1];
    
    struct Line
    {
        int y,x1,x2,d;
        Line() {}
        Line(int _y,int _x1,int _x2,int _d) : y(_y),x1(_x1),x2(_x2),d(_d) {}
    }line[N << 1];
    
    struct node
    {
        int Max,lazy;
    }T[N << 3];
    
    int b[N << 1];
    
    bool compare(const struct Line &x,const struct Line &y)
    {
        if(x.y == y.y) return x.d < y.d;
        return x.y < y.y;
    }
    
    void build(int root,int l,int r)
    {
        if(l == r)
        {
            T[root].Max = T[root].lazy = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1,l,mid);
        build(root << 1 | 1,mid + 1,r);
        T[root].Max = max(T[root << 1].Max,T[root << 1 | 1].Max);
        T[root].lazy = 0;
        return;
    }
    
    void pushdown(int root,int l,int r)
    {
        if(T[root].lazy == 0) return;
        int mid = (l + r) >> 1,tag = T[root].lazy;
        T[root << 1].lazy += tag;
        T[root << 1 | 1].lazy += tag;
        T[root << 1].Max += tag;
        T[root << 1 | 1].Max += tag;
        T[root].lazy = 0;
        return;
    }
    
    void update(int root,int l,int r,int s,int t,int d)
    {
        if(l <= s && t <= r)
        {
            T[root].Max += d;
            T[root].lazy += d;
            return;
        }
        pushdown(root,s,t);
        int mid = (s + t) >> 1;
        if(l <= mid) update(root << 1,l,r,s,mid,d);
        if(r > mid) update(root << 1 | 1,l,r,mid + 1,t,d);
        T[root].Max = max(T[root << 1].Max,T[root << 1 | 1].Max);
        return;
    }
    
    signed main(void)
    {   
        scanf("%lld",&Test);
        while(~scanf("%lld%lld%lld",&n,&w,&h))
        {
            
            for(int i = 1; i <= n; i++)
            {
                scanf("%lld %lld %lld",&a[i].x,&a[i].y,&a[i].l);
                line[i * 2 - 1] = Line(a[i].y,a[i].x,a[i].x + w - 1,a[i].l);
                line[i * 2] = Line(a[i].y + h,a[i].x,a[i].x + w - 1,-a[i].l);
                b[i * 2 - 1] = a[i].x,b[i * 2] = a[i].x + w - 1;
            }
            n <<= 1;
            sort(b + 1, b + n + 1);
            sort(line + 1, line + n + 1, compare);
            int L = unique(b + 1, b + n + 1) - b - 1;
            build(1,1,L);
            int ans = 0;
            for(int i = 1; i <= n; i++)
            {
                line[i].x1 = lower_bound(b + 1, b + L + 1, line[i].x1) - b;
                line[i].x2 = lower_bound(b + 1, b + L + 1, line[i].x2) - b;
                update(1,line[i].x1,line[i].x2,1,L,line[i].d);
                ans = max(ans,T[1].Max);
            }
            printf("%lld
    ",ans);
        }
        
        return 0;
    }
    
  • 相关阅读:
    windows C++ 获得一个进程的线程数目
    乌龟 SVN 在update后,如何知道 update前的版本号?
    C++ 类中的static对象貌似不能是类对象
    WinForms C#:html编辑器工程源码,含直接写WebBrowser的文件流、IPersistStreamInit接口的声明和一些相关的小方法
    用Remoting 实现一个文件传输组件
    [转载]Extreme Game Programming
    C#:10进制转2进制函数
    bindows 源码格式化工具(测试中的测试)C#源码
    明天又是周末,可以好好休息了!
    将文件加入到图形文件里;
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/14726673.html
Copyright © 2020-2023  润新知