zoukankan      html  css  js  c++  java
  • P4390 [BOI2007]Mokia 摩基亚 题解

    \(Description\)

    Luogu传送门

    \(Solution\)

    CDQ分治板题

    由于找一个矩形并不好处理,利用类似于二维前缀和的思想,把一个矩形拆成从 \((1, 1)\) 开始的 4 个矩形。

    具体是哪 4 个从 \((1, 1)\) 开始的矩形自己手推一下吧,懒得打了。

    考虑什么样的矩形对 \((x, y)\) 有贡献。

    那么它需要满足三个条件:

    1. \((x, y)\) 这个点之前出现。
    2. \(x_2 < x\)
    3. \(y_2 < y\)

    于是这道题就变成了经典的三维偏序问题!

    所以它就是个 \(CDQ\) 分治板子题。

    注意这题的边界有点小问题,二维前缀和中我们要用到 \((x_1 - 1, y_1 - 1)\),但这可能是 0,所以输入时把所有坐标 +1 即可,包括 \(w\)

    \(Code\)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace IO{
        inline int read(){
            int x = 0;
            char ch = getchar();
            while(!isdigit(ch)) ch = getchar();
            while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
            return x;
        }
    
        template <typename T> inline void write(T x){
            if(x > 9) write(x / 10);
            putchar(x % 10 + '0');
        }
    }
    using namespace IO;
    
    const int N = 2e5 + 10;
    const int M = 2e6 + 10;
    struct node{
        int op, id, x, y, val;
        bool operator < (const node &b) const{
            return x != b.x ? x < b.x : y < b.y;
        }
    }p[N];
    int n, op, w;
    
    namespace BIT{
        int c[M];
    
        inline void add(int x, int y){
            for(; x <= w; x += x & (-x)) c[x] += y;
        }
    
        inline int qry(int x){
            int res = 0;
            for(; x; x -= x & (-x)) res += c[x];
            return res;
        }
    }
    using namespace BIT;
    
    inline bool cmp(node a, node b){
        return a.id < b.id;
    }
    
    inline void CDQ(int l, int r){
        if(l == r) return;
        int mid = (l + r) >> 1;
        CDQ(l, mid), CDQ(mid + 1, r);
        sort(p + l, p + mid + 1);
        sort(p + mid + 1, p + r + 1);
        int i = l, j = mid + 1;
        while(j <= r){
            while(p[i].x <= p[j].x && i <= mid){
                if(!p[i].op) add(p[i].y, p[i].val);
                ++i;
            }
            if(p[j].op) p[j].val += qry(p[j].y);
            ++j;
        }
        for(j = l; j < i; ++j)
            if(!p[j].op) add(p[j].y, -p[j].val);
    }
    
    int main(){
        op = read(), w = read() + 1;
        while(op != 3){
            op = read();
            if(op == 1){
                int x = read() + 1, y = read() + 1, a = read();
                p[++n] = (node){0, n, x, y, a};
            }else if(op == 2){
                int x1 = read(), y1 = read(), x2 = read() + 1, y2 = read() + 1;
                p[++n] = (node){1, n, x1, y1, 0};
                p[++n] = (node){1, n, x2, y2, 0};
                p[++n] = (node){1, n, x2, y1, 0};
                p[++n] = (node){1, n, x1, y2, 0};
            }
        }
        CDQ(1, n);
        sort(p + 1, p + 1 + n, cmp);
        for(int i = 1; i <= n; ++i)
            if(p[i].op) write(p[i].val + p[i + 1].val - p[i + 2].val - p[i + 3].val), puts(""), i += 3;
        return 0;
    }
    

    \[\_EOF\_ \]

  • 相关阅读:
    封装和参数调用(格式修改)
    今天休息
    2018.1.9内部类
    2018.1.8转型
    环境变量
    环境变量
    计算机的高级语言
    常用的设计模式
    常用的设计模式
    【python3】中 elif 的使用
  • 原文地址:https://www.cnblogs.com/xixike/p/15814103.html
Copyright © 2011-2022 走看看