• [Luogu3801] 红色的幻想乡


    题目背景

    蕾米莉亚的红雾异变失败后,很不甘心。

    题目描述

    经过上次失败后,蕾米莉亚决定再次发动红雾异变,但为了防止被灵梦退治,她决定将红雾以奇怪的阵势释放。

    我们将幻想乡看做是一个n*m的方格地区,一开始没有任何一个地区被红雾遮盖。蕾米莉亚每次站在某一个地区上,向东南西北四个方向各发出一条无限长的红雾,可以影响到整行/整列,但不会影响到她所站的那个地区。如果两阵红雾碰撞,则会因为密度过大而沉降消失。灵梦察觉到了这次异变,决定去解决它。但在解决之前,灵梦想要了解一片范围红雾的密度。可以简述为两种操作:

    1 x y 蕾米莉亚站在坐标(x,y)的位置向四个方向释放无限长的红雾。

    2 x1 y1 x2 y2 询问左上点为(x1,y1),右下点为(x2,y2)的矩形范围内,被红雾遮盖的地区的数量。

    输入输出格式

    输入格式:

    第一行三个整数n,m,q,表示幻想乡大小为n*m,有q个询问。

    接下来q行,每行3个或5个整数,用空格隔开,含义见题目描述。

    输出格式:

    对于每一个操作2,输出一行一个整数,表示对应询问的答案。

    输入输出样例

    输入样例#1: 复制
    4 4 3
    1 2 2
    1 4 4
    2 1 1 4 4
    
    输出样例#1: 复制
    8

    说明

    样例解释:

    用o表示没有红雾,x表示有红雾,两次释放红雾后幻想乡地图如下:

    oxox

    xoxo

    oxox

    xoxo

    数据范围:

    对于20%的数据,1<=n,m,q<=200

    对于 40%的数据,1<=n,m,q<=1000

    对于100%的数据,1<=n,m,q<=100000

    1<=x1,x2,x<=n x1<=x2

    1<=y1,y2,y<=m y1<=y2

    by-orangebird


    题目中唯一一个看起来不太舒服的就是起点不被覆盖, 但是想想其实起点是因为行和列都有覆盖所以它没有。

    于是不用单独考虑起点的问题了。

    所以我们开两个线段树,分别维护行和列是否被覆盖。

    如果给定的区域的行的长度为$L1$, 列的长度为$L2$,行有$res1$个被覆盖, 列有$res2$个被覆盖。

    那么答案就是$large L1 * res2 + L2 * res1 - res1 * res2 * 2$。

    就是加上行上的个数,加上列上的个数, 然后行和列有交点, 交点都不会对答案产生贡献, 于是减去两倍的$res1*res2$。


    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <cmath>
    using namespace std;
    #define reg register 
    #define int long long
    inline int read() {
        int res = 0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return res;
    }
    #define N 100005
    int n, m, q;
    int tr1[N<<2], tr2[N<<2];
    #define ls(o) o << 1
    #define rs(o) o << 1 | 1
    
    void change1(int l, int r, int o, int pos)
    {
        if (l == r) {tr1[o] ^= 1;return ;}
        int mid = l + r >> 1;
        if (pos <= mid) change1(l, mid, ls(o), pos);
        else change1(mid + 1, r, rs(o), pos);
        tr1[o] = tr1[ls(o)] + tr1[rs(o)];
    }
    
    void change2(int l, int r, int o, int pos)
    {
        if (l == r) {tr2[o] ^= 1;return ;}
        int mid = l + r >> 1;
        if (pos <= mid) change2(l, mid, ls(o), pos);
        else change2(mid + 1, r, rs(o), pos);
        tr2[o] = tr2[ls(o)] + tr2[rs(o)];
    }
    
    int query1(int l, int r, int o, int ql, int qr)
    {
        if (l >= ql and r <= qr)
            return tr1[o];
        int mid = l + r >> 1;
        int res = 0;
        if (ql <= mid) res += query1(l, mid, ls(o), ql, qr);
        if (qr > mid) res += query1(mid + 1, r, rs(o), ql, qr);
        return res;
    }
    
    int query2(int l, int r, int o, int ql, int qr)
    {
        if (l >= ql and r <= qr)
            return tr2[o];
        int mid = l + r >> 1;
        int res = 0;
        if (ql <= mid) res += query2(l, mid, ls(o), ql, qr);
        if (qr > mid) res += query2(mid + 1, r, rs(o), ql, qr);
        return res;
    }
    
    signed main() 
    {
        n = read(), m = read(), q = read();
        while(q--)
        {
            int opt = read();
            if (opt == 1) {
                int x = read(), y = read();
                change1(1, n, 1, x), change2(1, n, 1, y);
            } else {
                int x1 = read(), y1 = read(), x2 = read(), y2 = read();
                int res1 = query1(1, n, 1, x1, x2), res2 = query2(1, n, 1, y1, y2);
                printf("%lld
    ", (x2 - x1 + 1) * res2 + (y2 - y1 + 1) * res1 - res1 * res2 * 2);
            }
        }
        return 0;
    }
  • 相关阅读:
    网格形变
    网格简化
    无法打开包括文件: “QWidget”: No such file or directory
    遇到一个 bug svg 抖动的解决方案
    echarts-gl 遇到一个错误 groupGL 未定义
    鼠标操控三维视角
    鼠标控制3维操作 不知道能不能获得一些灵感
    tensorflow 安装
    Codeforces Round #541 (Div. 2) B.Draw!
    Codeforces Round #541 (Div. 2) A.Sea Battle
  • 原文地址:https://www.cnblogs.com/BriMon/p/9609642.html
Copyright © 2020-2023  润新知