首页 > 其他分享 >题解:AT_abc136_f [ABC136F] Enclosed Points

题解:AT_abc136_f [ABC136F] Enclosed Points

时间:2025-01-14 16:13:42浏览次数:1  
标签:cnt ch 题解 times abc136 象限 Points 答案 二四

传送门

Solution

对于一个点 \(i\),我们将其与其它点匹配,故有 \(2^{n - 1}\) 的方案数,这是答案的初始。

对于每个点 \((x_i,y_i)\) 再建系,四个象限都可能会有点,我们此时考虑四个象限的点如何匹配,才能使 \((x_i,y_i)\) 包含其中,稍微手玩一下就可以发现,对于一四象限、二三象限的点匹配,是无法包含 \((x_i,y_i)\) 的,但是一三象限、二四象限就可以,考虑统计答案。

分别假设四个象限各有 \(cnt_1,cnt_2,cnt_3,cnt_4\) 个点:

  • 一三象限的答案:

    \[(2^{cnt_1} - 1) \times (2^{cnt_3} - 1) \]

  • 二四象限的答案:

    \[(2^{cnt_2} - 1) \times (2^{cnt_4} - 1) \]

然而这样是在其余两个象限都没有点存在的情况下,对于其余象限的所有点,任意选择或不选择都对答案不影响,故:

  • 一三象限的答案:

    \[(2^{cnt_1} - 1) \times (2^{cnt_3} - 1) \times 2^{cnt_2 + cnt_4} \]

  • 二四象限的答案:

    \[(2^{cnt_2} - 1) \times (2^{cnt_4} - 1) \times 2^{cnt_1 + cnt_3} \]

显然的,这样计算肯定会算重某些情况,考虑容斥。

我们对选择一三象限作限制,钦定其只能同时再选二或四象限,这样一来,选择二四象限时,可以任意选一三象限:

  • 一三象限的答案:

    \[(2^{cnt_1} - 1) \times (2^{cnt_3} - 1) \times 2^{cnt_2} + (2^{cnt_1} - 1) \times (2^{cnt_3} - 1) \times 2^{cnt_4} \]

  • 二四象限的答案:

    \[(2^{cnt_2} - 1) \times (2^{cnt_4} - 1) \times 2^{cnt_1 + cnt_3} \]

这样就可以避免选重的情况,现在考虑如何维护这个东西。

这里选用线段树维护,分别维护当前点左侧、右侧点数,总复杂度 \(O(n \log n)\)。

Code

#include <bits/stdc++.h>
#define int long long

using namespace std;
namespace FASTIO {
    inline int read() {
        int res = 0, f = 1;
        char ch = getchar();
        while (!isdigit (ch)) f = ch == '-' ? -1 : 1, ch = getchar();
        while (isdigit (ch)) res = (res << 1) + (res << 3) + (ch ^ 48), ch = getchar();
        return res * f;
    }
    inline void write (int x) {
        int st[33], top = 0;
        do { st[top ++] = x % 10, x /= 10; } while (x);
        while (top) putchar (st[-- top] + '0');
    }
};
using namespace FASTIO;
const int MAXN = 2e5 + 10, MOD = 998244353;
int n, cpy[MAXN], Answer, pw2[MAXN];
struct Ayaka { int x, y; } pt[MAXN];
inline bool Cmp (Ayaka s1, Ayaka s2) { return s1.x < s2.x; }
struct Segmentree { int l, r, appTim; } seg[2][MAXN << 2]; /* appTim 表示点出现的次数,即象限内点数 */

/* seg[0] 的一维维护当前点左侧点数,seg[1] 的一维维护右侧 */

inline void pushup (int rt, int p) { seg[p][rt].appTim = seg[p][rt << 1].appTim + seg[p][rt << 1 | 1].appTim; }

void Build (int l, int r, int rt, int p) {
    seg[p][rt].l = l, seg[p][rt].r = r, seg[p][rt].appTim = 0;
    if (l == r) return;
    int mid = l + r >> 1;
    Build (l, mid, rt << 1, p), Build (mid + 1, r, rt << 1 | 1, p);
    pushup (rt, p);
}

void update (int rt, int p, int pos, int k) {
    int l = seg[p][rt].l, r = seg[p][rt].r;
    if (l == r) {
        seg[p][rt].appTim += k;
        return;
    }
    int mid = l + r >> 1;
    if (pos <= mid)
        update (rt << 1, p, pos, k);
    else
        update (rt << 1 | 1, p, pos, k);
    pushup (rt, p);
}

int query (int ql, int qr, int rt, int p) {
    int l = seg[p][rt].l, r = seg[p][rt].r;
    if (ql <= l && qr >= r)
        return seg[p][rt].appTim;
    int mid = l + r >> 1, tmpAns = 0;
    if (ql <= mid)
        tmpAns = (tmpAns + query (ql, qr, rt << 1, p)) % MOD;
    if (qr > mid)
        tmpAns = (tmpAns + query (ql, qr, rt << 1 | 1, p)) % MOD;
    return tmpAns;
}

inline void Getpw2() {
    pw2[0] = 1;
    for (int i = 1; i < MAXN; i ++)
        pw2[i] = (pw2[i - 1] << 1) % MOD;
    return;
}

signed main() {
    n = read(), Getpw2();
    for (int i = 1; i <= n; i ++)
        pt[i].x = read(), pt[i].y = read(), cpy[i] = pt[i].y;
    sort (cpy + 1, cpy + n + 1), sort (pt + 1, pt + n + 1, Cmp);
    /* 将点按照 x 坐标排序 */
    Build (1, MAXN - 1, 1, 0), Build (1, MAXN - 1, 1, 1);
    for (int i = 1; i <= n; i ++) {
        int ptr = lower_bound (cpy + 1, cpy + n + 1, pt[i].y) - cpy;
        update (1, 1, ptr, 1);
        /* 先将所有点插入到当前点右侧 */
    }
    for (int i = 1; i <= n; i ++) {
        int ptr = lower_bound (cpy + 1, cpy + n + 1, pt[i].y) - cpy;
        update (1, 1, ptr, -1);
        /* 从右侧删除当前点 */
        int upL = query (1, ptr - 1, 1, 0), downL = query (1, ptr - 1, 1, 1); 
        /* 左下左上的点数 */
        int upR = query (ptr + 1, MAXN - 1, 1, 0), downR = query (ptr + 1, MAXN - 1, 1, 1);
        /* 右下右上的点数 */
        int tmpAnsL = (pw2[upL] - 1) * (pw2[downR] - 1) % MOD, tmpAnsR = (pw2[downL] - 1) * (pw2[upR] - 1) % MOD;
        Answer = ((Answer + tmpAnsL) % MOD + tmpAnsR) % MOD;
        if (downL) Answer = (Answer + tmpAnsL * (pw2[downL] - 1) % MOD) % MOD;
        /* 若左下存在点,新增答案 */
        if (upR) Answer = (Answer + tmpAnsL * (pw2[upR] - 1) % MOD) % MOD;
        /* 若右上存在点,新增答案 */
        Answer = (Answer + tmpAnsR * (pw2[upL + downR] - 1) % MOD) % MOD;
        /* 对于无限制的左上右下再次新增答案 */
        Answer = (Answer + pw2[n - 1]) % MOD;
        /* 一开始任意匹配的答案 */
        update (1, 0, ptr, 1);
        /* 向左侧插入当前点 */
    }
    write (Answer), putchar ('\n');
    return 0;
}

标签:cnt,ch,题解,times,abc136,象限,Points,答案,二四
From: https://www.cnblogs.com/Ayaka-0928/p/18671002

相关文章

  • [ABC136F] Enclosed Points
    前言模拟赛\(\rm{T1}\),全世界都切出来了思路首先容易想到换贡献主体,容易想到按点计算贡献(所以我赛时为什么叉掉这个直接去按矩阵算贡献了,无语)考虑对于一个点,其贡献的来源:只要有一个子集构成的矩形包含它,就会产生贡献问题转化为对于一个点,有多少个子集包含......
  • 记录在虚拟机中达梦数据库DEM安装过程遇到的问题解决方法
    本篇博客是记录了在寒假课程设计中在虚拟机麒麟银河系统安装达梦数据库DEM遇到的各种刁钻问题的解决方法,希望同样遇到这些问题的小伙伴们能够在查看本篇博客后真正解决问题。废话不多说,直接往下看吧! dem服务器的安装与部署1、上传dem和tomcat压缩包2、./dminitpath=/d......
  • ABC382&ABC383题解
    [ABC382C]KaitenSushi题目描述有\(N\)个人,编号从\(1\)到\(N\),他们正在访问一家传送带寿司餐厅。第\(i\)个人的美食级别是\(A_i\)。现在,将会有\(M\)份寿司放置在传送带上。第\(j\)份寿司的美味度为\(B_j\)。每份寿司将按照顺序经过编号为\(1\),\(2\),\(\dots\),\(N......
  • [CCO2021] Through Another Maze Darkly 题解
    思路很牛,代码很难,故写题解记之。前置知识:线段树。洛谷题目链接:P7830[CCO2021]ThroughAnotherMazeDarkly。原题题面很简洁,故不赘述题意。观察(70%)读完题,这是什么东西。我们直接去手玩样例,然后发现几个很有用的信息:一个点被进入一次后,必然会指针朝上。一个点被进......
  • 英雄联盟游戏黑屏有声音 原因分析及问题解决
    英雄联盟作为一款热门游戏,经常有玩家遇上电脑黑屏,但却可以听到游戏内的声音,这是怎么回事?这通常意味着显卡驱动程序可能遇到了某些问题,也可能与游戏文件损坏、系统设置不当等因素有关。以下是一些常见的解决方法:一、显卡问题更新显卡驱动:显卡驱动不兼容或过时可能导致游戏......
  • 题解:AT_abc353_f [ABC353F] Tile Distance
    [ABC353F]TileDistance题解cnblogs题目传送门:洛谷,AtcoderSolution很恶心人的分类讨论题。很显然走大格子大概率比走小格子快。对终点和起点向上下左右枚举大格子,我们就把问题转化为给两个大格子\((a,b)\)、\((c,d)\),求怎样走最快。对角的大格子可以通过\(2\)步相互到......
  • ABC388DEG 题解
    ABC388题解ABCDE+G,rk371。D观察到几个性质:一个人只会在成年的时候得到石头,在成年之后给出石头。第\(i\)个人成年之后,他要给之后的每个人一个石头(除非用光了)。也就是说,假设成年时它的石头数量为\(B_i\),则最终他的石头数量为\(\max(0,B_i-(n-i))\)。因此我们只需......
  • LeetCode 2275: 按位与结果大于零的最长组合题解
    LeetCode2275:按位与结果大于零的最长组合题解1.题目分析这道题目考察了位运算的基本概念和应用。我们需要在给定的数组中找出最长的子序列,使得这些数字进行按位与运算后的结果大于0。1.1关键概念按位与运算(&)两个二进制位都为1时,结果为1。只要有一个为0,结果就为0......
  • 【大数据】beeline 导出文件有特殊字符的问题解决
    问题近期在做大数据查询引擎导出文件的功能,使用了hive的beeline客户端。发现beeline导出的文件以及终端输出有许多特殊字符。按照官方文档使用beeline导出命令:[1]/usr/bin/beeline--silent=true--showHeader=true--outputformat=csv2-fquery.hql</dev/null>/tm......
  • Hetao P3804 Cut 题解 [ 蓝 ] [ AC 自动机 ] [ 差分 ]
    Cut:AC自动机简单题。思路看见多个模式串以及求前缀,很显然能想到构建一个AC自动机。那么在用\(T\)查询时,当前指针的深度就是该位置的最长前缀匹配长度。这个在字典树insert的时候就能求出来。求出每一位的最长前缀后,因为这些部分都不能作为分割点,所以将这些区域用差分......