• P4390 [BOI2007]Mokia 摩基亚 (CDQ解决三维偏序问题)


    题目描述

    摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统。和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米。但其真正高科技之处在于,它能够回答形如“给定区域内有多少名用户?”的问题。

    在定位系统中,世界被认为是一个W×W的正方形区域,由1×1的方格组成。每个方格都有一个坐标(x,y),1<=x,y<=W。坐标的编号从1开始。对于一个4×4的正方形,就有1<=x<=4,1<=y<=4(如图):

    img

    请帮助Mokia公司编写一个程序来计算在某个矩形区域内有多少名用户。

    输入格式

    有三种命令,意义如下:

    命令 参数 意义

    • 0 W 初始化一个全零矩阵。本命令仅开始时出现一次。
    • 1 x y A 向方格(x,y)中添加A个用户。A是正整数。
    • 2 X1 Y1 X2 Y2 查询X1<=x<=X2,Y1<=y<=Y2所规定的矩形中的用户数量
    • 3 无参数 结束程序。本命令仅结束时出现一次。

    输出格式

    对所有命令2,输出一个一行整数,即当前询问矩形内的用户数量。

    输入输出样例

    输入 #1复制

    0 4
    1 2 3 3
    2 1 1 3 3
    1 2 2 2
    2 2 2 3 4
    3
    

    输出 #1复制

    3
    5
    

    说明/提示

    对于所有数据:

    1<=W<=2000000
    1<=X1<=X2<=W
    1<=Y1<=Y2<=W
    1<=x,y<=W
    0<A<=10000
    命令1不超过160000个。
    命令2不超过10000个。

    思路:

    经典的CDQ解决带修改的三维偏序问题。

    第一维time,默认有序。

    第二维x坐标,用归并排序结局。

    第三维y坐标,用树状数组维护动态前缀和。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define du2(a,b) scanf("%d %d",&(a),&(b))
    #define du1(a) scanf("%d",&(a));
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
    void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    
    inline void getInt(int *p);
    const int maxn = 1000010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int op;
    int n;
    const int maxL = 3000010;
    ll tree[maxL];
    int lowbit(int x)
    {
        return -x & x;
    }
    ll ask(int x)
    {
        ll res = 0ll;
        while (x) {
            res += tree[x];
            x -= lowbit(x);
        }
        return res;
    }
    void add(int x, ll val)
    {
        while (x < maxL) {
            tree[x] += val;
            x += lowbit(x);
        }
    }
    
    struct node {
        int t;
        int op;
        int x, y;
        int k;
        int val;
        node() {}
        node(int tt, int oo, int xx, int yy, int kk, int vv)
        {
            t = tt;
            op = oo;
            x = xx;
            y = yy;
            k = kk;
            val = vv;
        }
        bool operator<= (const node &bb )const
        {
            if (x != bb.x) {
                return x < bb.x;
            } else {
                return y <= bb.y;
            }
        }
    };
    node a[maxn];
    node b[maxn];
    ll ans[maxn];
    int tot;
    int anstot;
    
    
    void cdq(int l, int r)
    {
        if (l == r) {
            return ;
        }
        int mid = (l + r) >> 1;
        cdq(l, mid);
        cdq(mid + 1, r);
        int ql = l;
        int qr = mid + 1;
        repd(i, l, r) {
            if (qr > r || (ql <= mid && a[ql] <= a[qr])) {
                if (a[ql].op == 1) {
                    add(a[ql].y, a[ql].val);
                }
                b[i] = a[ql++];
            } else {
                if (a[qr].op == 2) {
                    ans[a[qr].val] += a[qr].k * ask(a[qr].y);
                }
                b[i] = a[qr++];
            }
        }
        ql = l;
        qr = mid + 1;
        repd(i, l, r) {
            if (qr > r || (ql <= mid && a[ql] <= a[qr])) {
                if (a[ql].op == 1) {
                    add(a[ql].y, -a[ql].val);
                }
                ql++;
            } else {
                qr++;
            }
        }
        repd(i, l, r) {
            a[i] = b[i];
        }
    }
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        while (~scanf("%d", &op)) {
            if (op == 0) {
                scanf("%d", &n);
            } else if (op == 1) {
                int x, y, c;
                du3(x, y, c);
                x++;
                y++;
                tot++;
                a[tot] = node(tot, 1, x, y, 0, c);
            } else if (op == 2) {
                int x1, y1, x2, y2;
                du2(x1, y1); du2(x2, y2);
                x1++;
                y1++;
                x2++;
                y2++;
                tot++;
                a[tot] = node(tot, 2, x1 - 1, y1 - 1, 1, ++anstot);
                tot++;
                a[tot] = node(tot, 2, x1 - 1, y2, -1, anstot);
                tot++;
                a[tot] = node(tot, 2, x2, y1 - 1, -1, anstot);
                tot++;
                a[tot] = node(tot, 2, x2, y2, 1, anstot);
            } else {
                break;
            }
        }
        cdq(1, tot);
        repd(i, 1, anstot) {
            printf("%lld
    ", ans[i]);
        }
    
        return 0;
    }
    
    inline void getInt(int *p)
    {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        } else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    Pagination 分页类
    FckEditorAPI未定义错误分析
    提取DataSet数据集中前N条记录
    JS操作JSON[转]
    JS运行textarea内的HTML代码 [转]
    使用Global.asax文件统计网站总访问量
    文章点击数简单实现周、月、年排行
    asp.net文件下载[转]
    三大策略保证论坛不受垃圾信息影响![转]
    图片以二进制形式写入数据库并显示
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11613573.html
Copyright © 2020-2023  润新知