首页 > 其他分享 >P1502 窗口的星星 题解

P1502 窗口的星星 题解

时间:2024-08-11 15:27:09浏览次数:14  
标签:星星 rt ch P1502 题解 LL tr add 矩形

题目传送门

思路

扫描线

扫描线

首先,将题目中给出的条件和问题进行转化:

首先先不考虑边框上的点不算在内的限制,考虑一个点可以对那些矩形产生贡献。

只考虑矩形的右上角,容易发现,每个星星的亮度只对右上角在以星星为左下角的长为 \(W\),高为 \(H\)的矩形有贡献。
如图。

那么便可以把问题进行转化:在平面直角坐标系上有 \(n\) 个有权值矩形,求他们最大的重合的权值。

于是就可以用扫描线来解决了。

再考虑边框上的点不算在内的限制,因为可以这样框:

有效的矩形就相当于 \(W - 1\),\(H - 1\) 的能取边框上的点的矩形,然后像上面那样做就可以了。

细节

对线进行排序时,要注意若两条线重合,应按权值从大到小排序。
因为可能两个矩形贴合,而又能取矩形边框上的点,所以不排序的话权值可能算小。

点击查看代码

代码

/*
  --------------------------------
  |        code by FRZ_29        |
  |          code  time          |
  |          2024/08/11          |
  |           11:02:16           |
  |             星期天            |
  --------------------------------
                                  */

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
typedef long long LL;

using namespace std;

void RD() {}
template<typename T, typename... U> void RD(T &x, U&... arg) {
    x = 0; LL f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    x *= f; RD(arg...);
}

const LL N = 1e4 + 5;

#define LS (rt << 1)
#define RS (rt << 1 | 1)
#define MID (l + r >> 1)
#define LF(i, __l, __r) for (LL i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (LL i = __r; i >= __l; i--)

struct tree{
    LL l, r, mx, add;
    tree(LL l = 0, LL r = 0, LL mx = 0, LL add = 0) : l(l), r(r), mx(mx), add(add) {}
} tr[N << 4];
struct seg {
    LL l, r, h, val;
    seg(LL l = 0, LL r = 0, LL h = 0, LL val = 0) : l(l), r(r), h(h), val(val) {}
} a[N << 1];
LL t, n, w, h, Y[N << 1];

void up(LL rt) { tr[rt].mx = max(tr[LS].mx, tr[RS].mx); }
bool cmp(seg a, seg b) { return (a.h != b.h ? a.h < b.h : a.val > b.val); }

void Init() {
    memset(a, 0, sizeof(a));
    memset(tr, 0, sizeof(tr));
}

void build(LL rt, LL l, LL r) {
    tr[rt] = tree(l, r, 0LL, 0LL);
    if (l == r) return;
    build(LS, l, MID), build(RS, MID + 1, r);
}

void down(LL rt) {
    tr[LS].mx += tr[rt].add;
    tr[RS].mx += tr[rt].add;
    tr[LS].add += tr[rt].add;
    tr[RS].add += tr[rt].add;
    tr[rt].add = 0;
}

void update(LL rt, LL L, LL R, LL val) {
    LL l = tr[rt].l, r = tr[rt].r;
    
    if (L <= l && r <= R) {
        tr[rt].mx += val;
        tr[rt].add += val;
        return;
    }

    down(rt);
    if (L <= MID) update(LS, L, R, val);
    if (R > MID) update(RS, L, R, val);
    up(rt);
}

int main() {
    RD(t);

    while (t--) {
        Init();
        RD(n, w, h);
        w--, h--;

        LF(i, 1, n) {
            LL x, y, l;
            RD(x, y, l);
            Y[2 * i - 1] = y, Y[2 * i] = y + h;
            a[2 * i - 1] = seg(y, y + h, x, l);
            a[2 * i] = seg(y, y + h, x + w, -l);
        }

        n <<= 1;
        sort(Y + 1, Y + n + 1);
        LL len = unique(Y + 1, Y + n + 1) - Y - 1;
        sort(a + 1, a + n + 1, cmp);

        LF(i, 1, n) {
            LL low_l = lower_bound(Y + 1, Y + len + 1, a[i].l) - Y;
            LL low_r = lower_bound(Y + 1, Y + len + 1, a[i].r) - Y;
            a[i].l = low_l, a[i].r = low_r;
        }

        build(1, 1, len);
        LL ans = 0;

        LF(i, 1, n) {
            update(1, a[i].l, a[i].r, a[i].val);
            ans = max(ans, tr[1].mx);
        }

        printf("%lld\n", ans);
    }
    return 0;
}

/* 
 * ps:FRZ弱爆了 
 * 感冒写的代码唐爆了……
 */

前尘隔海,古屋不再。

标签:星星,rt,ch,P1502,题解,LL,tr,add,矩形
From: https://www.cnblogs.com/FRZ29/p/18353478

相关文章

  • 洛谷 4道水题 题解(字符串入门)
    题目目录:No.1 B2109统计数字字符个数 No.2 B2110找第一个只出现一次的字符 No.3 B2111基因相关性No.4 B2113输出亲朋字符串OK开始正文!第一题:B2109统计数字字符个数题目描述输入一行字符,统计出其中数字字符的个数。输入格式一行字符串,总长度不超过 255。......
  • ABC366简要题解
    C直接维护一个桶,表示每个元素当前的出现次数。再利用这个桶直接维护答案即可。D三维前缀和模板题。E注意到答案中只会出现\(O(n)\)个不同\(x\),以及\(O(n)\)个不同的\(y\)。于是单独考虑\(x\)和\(y\),最后尺取求一下答案即可。F首先我第一个尝试的思路是贪心,但是......
  • Buuctf-Mysterious另类逆向题解
    下载发现是一个exe可执行文件双击运行,输入密码123456没有任何反应,当然没反应,密码肯定不对请出IDApro,我这里用IDAProv8.3演示,把exe文件拖拽到IDA打开按shift+F12快捷键搜索字符串我们发现第二行有可疑字符串,有flag嫌疑,双击上面的welldonewelldone里“Buff3r_0......
  • Codeforces Round 965 (Div. 2) 题解
    个人难度顺序:A<D<B<C<E。A.FindKDistinctPointswithFixedCenter如果\(k\)是偶数,构造\((x_c+i,yc+i)\),其中\(-\frac{k}{2}\lei\le\frac{k}{2}\)。对于\(k\)是奇数,先加一个点\((xc,yc)\),然后就变成偶数的情况了。B.MinimizeEqualSumSubarr......
  • ABC366-D 题解
    三维前缀和板子。三维前缀和可以类似二维前缀和来做,先给一下二维前缀和数组的计算方法:\[sum_{i,j}=a_{i,j}+sum_{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1}\]同样的,可以写出三维前缀和数组的计算方法:\[sum_{i,j,k}=a_{i,j,k}+sum_{i,j,k-1}+sum_{i,j-1,k}+sum_{i-1,j,k}-sum_{i,j-1,k......
  • [COCI2015-2016#3] NEKAMELEONI 题解
    前言题目链接:洛谷。题意简述你要维护一个序列\(a_i\in[1,k]\)(\(k\leq50\)),支持:单点修改;询问最短的包含全部\(1\simk\)的自区间长度,或报告无解。题目分析我想到了两种做法,写题解以加深印象。方法\(1\):直接用线段树维护只有单点修改,尝试用线段树维护分治。考虑......
  • AtCoder Beginner Contest 366 C,D题解
    C-BallsandBagQuery题解题意没什么好说的,给出q次查询,进行求解思路很简单的一道题,但这篇题解的作用是引出unordered_set,这个东西的作用类似set,但没有排序,相当于哈希。unordered_set有几种操作,接下来介绍三种insert,没什么可说的,普通的插入erase,进行弹出size,返回大......
  • ABC 366 题解
    AtCoderBeginnerContest366题解:\(Problem\hspace{2mm}A-Election\hspace{2mm}2\)题目链接opinion:很显然,当一个人的票数大于等于\(\lceil\frac{n}{2}\rceil\)时此人一定当选。(或可理解为投票结果一定固定。)依次判断两人即可。code:#include<bits/stdc++......
  • CF1674G Remove Directed Edges 题解
    CF1674G给出一个\(n\)点\(m\)边的有向无环图,你需要从中移除一些边,使得对于每一个点,其入度减少(如果原来有入边),出度也减少(如果原来有出边)。当删完边以后,如果有一个点集,满足对于任两点\((i,j)\)可以从\(i\)走到\(j\)或可以从\(j\)走到\(i\),那就称其为可爱的。现在要......
  • CF1863E Speedrun 题解
    CF1863E你在玩一个游戏,要完成\(n\)个任务。其中对于每个任务\(i\),它只能在某一天的第\(h_i\)时刻完成。游戏每天有\(k\)个小时,分别编号为\(0,1,...k-1\)。给出\(m\)对任务间的依赖关系,\((a_i,b_i)\)表示\(a_i\)必须比\(b_i\)先完成。保证依赖关系不形成环。完......