• 【Codeforces Round #433 (Div. 1) C】Boredom(二维线段树)


    【链接】我是链接


    【题意】



    【题解】


    这里讲一种用类似二维线段树的方法求矩形区域内点的个数的方法。
    我们可以把n个正方形用n棵线段树来维护。
    第i棵线段树维护的是正方形的前i列的各行之间的点数之和。
    也即前i列,第[x..y]行之间点的个数(也即一个(y-x+1)*i的矩形区域的点的个数);
    因为每一列只有一个点。
    所以,我们在输入的时候,当前的“行区间l..r”的点数和,直接加上1就好。
    然后看看输入的点所在的行区间在l..m还是m+1..r
    如果是在l..m,则右区间直接用前一列的线段树的相应节点就好。不用重新建树(因为点数就和前i-1列的一样)。
    左区间还是一样,在前一列的基础上点数和递增1.
    询问(x1,y1)~(x2,y2)这个矩形区域的时候。
    只要在第x1-1列的线段树里面求和第y1..y2行的点个数sum2。
    在第x2列的线段树里面也求和第y1..y2行的点个数sum1;
    则sum1-sum2就是这个矩形区域内的点的个数了。
    其他的和上一篇文章类似。

    【错的次数】


    0

    【反思】


    在这了写反思

    【代码】

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 2e5, M = 2e5 * 20;
    
    int n, q;
    int root[N + 10], ls[M + 10], rs[M + 10], sum[M+10],tot = 0;
    long long ans = 0;
    
    void updata(int &x, int y, int l, int r, int pos) {
        x = ++tot;
        ls[x] = ls[y], rs[x] = rs[y];
        sum[x] = sum[y] + 1;    
        int m = (l + r) >> 1;
        if (l == r) return;
        if (pos <= m)
            updata(ls[x], ls[y], l, m, pos);
        else
            updata(rs[x], rs[y], m + 1, r, pos);
    }
    
    int Q(int x, int L, int R, int l, int r) {
        if (!x) return 0;
        if (L <= l && r <= R) return sum[x];
        int m = (l + r) >> 1;
        int sum = 0;
        if (L <= m) sum += Q(ls[x], L, R, l, m);
        if (m < R) sum += Q(rs[x], L, R, m + 1, r);
        return sum;
    }
    
    long long C(long long x) {
        return x*(x - 1)/2;
    }
    
    long long ask(int x1, int y1, int x2, int y2) {
        return C(Q(root[x2], y1, y2, 1, n) - Q(root[x1 - 1], y1, y2, 1, n));
    }
    
    int main() {
        ios::sync_with_stdio(0), cin.tie(0);
        cin >> n >> q;
        for (int i = 1,p; i <= n; i++) {
            cin >> p;
            updata(root[i],root[i-1],1,n,p);
        }
        for (int i = 1, l, d, r, u; i <= q; i++) {
            cin >> l >> d >> r >> u;
            ans = ask(1, 1, l - 1, n) + ask(1, 1, n, d - 1) + ask(r + 1, 1, n, n) + ask(1, u + 1, n, n);
            ans = ans - ask(1, 1, l - 1, d - 1) - ask(1, u + 1, l - 1, n) - ask(r + 1, u + 1, n, n) - ask(r + 1, 1, n, d - 1);
            cout << C(n) - ans << endl;
        }
        return 0;
    }


  • 相关阅读:
    js实现点击隐藏图片
    绝对定位给图片四角加上图片修饰
    雪碧图实现登陆页面
    弹性盒模型
    数组练习--求数组和,平均值,最大值,最小值
    h5与c3权威指南笔记--css3结构性伪类选择器root,not,empty,target
    h5与c3权威指南笔记--css3新属性选择器
    闲聊Java里的随机数
    Python之简单抓取豆瓣读书信息
    中本聪比特币论文
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626017.html
Copyright © 2020-2023  润新知