zoukankan      html  css  js  c++  java
  • 洛谷 P2163 [SHOI2007]园丁的烦恼 (离线sort,树状数组,解决三维偏序问题)

    P2163 [SHOI2007]园丁的烦恼

    题目描述

    很久很久以前,在遥远的大陆上有一个美丽的国家。统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草。

    有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……”

    “那么本质上它是一个深度优先搜索,陛下”,园丁深深地向国王鞠了一躬。

    “嗯……我听说有一种怪物叫九头蛇,它非常贪吃苹果树……”

    “是的,显然这是一道经典的动态规划题,早在N元4002年我们就已经发现了其中的奥秘了,陛下”。

    “该死的,你究竟是什么来头?”

    “陛下息怒,干我们的这行经常莫名其妙地被问到和OI有关的题目,我也是为了预防万一啊!” 王者的尊严受到了伤害,这是不可容忍的。

    看来一般的难题是难不倒这位园丁的,国王最后打算用车轮战来消耗他的实力: “年轻人,在我的花园里的每一棵树可以用一个整数坐标来表示,一会儿,我的骑士们会来轮番询问你某一个矩阵内有多少树,如果你不能立即答对,你就准备走人吧!”说完,国王气呼呼地先走了。

    这下轮到园丁傻眼了,他没有准备过这样的问题。所幸的是,作为“全国园丁保护联盟”的会长——你,可以成为他的最后一根救命稻草。

    输入格式

    第一行有两个整数n,m(0≤n≤500000,1≤m≤500000)。n代表皇家花园的树木的总数,m代表骑士们询问的次数。

    文件接下来的n行,每行都有两个整数xi,yi,代表第i棵树的坐标(0≤xi,yi≤10000000)。

    文件的最后m行,每行都有四个整数aj,bj,cj,dj,表示第j次询问,其中所问的矩形以(aj,bj)为左下坐标,以(cj,dj)为右上坐标。

    输出格式

    共输出m行,每行一个整数,即回答国王以(aj,bj)和(cj,dj)为界的矩形里有多少棵树。

    输入输出样例

    输入 #1复制

    3 1
    0 0 
    0 1
    1 0
    0 0 1 1
    

    输出 #1复制

    3
    

    思路:

    三维偏序解决二维平面中矩形包括多少个点数问题。

    维度:

    {

    ​ x轴

    ​ y轴

    ​ 操作类型

    }

    我们把初始给定的n个点转为向坐标系中加点的操作

    m个询问转为询问问题。

    那么按照x,y升序排序,想x和y都相等时,加点的操作优先。

    通过二维前缀和性质,把询问分解为四个(0,0)节点为左下角子询问积累贡献求得。

    排序后,利用树桩数组来维护答案。

    代码:

    #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 = 3000010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    
    ll tree[maxn];
    int lowbit(int x)
    {
        return -x & x;
    }
    ll ask(int x)
    {
        ll res = 0ll;
        while (x) {
            res += tree[x];
            x -= lowbit(x);
        }
        return res;
    }
    int my=0;
    void add(int x, ll val)
    {
        while (x < my) {
            tree[x] += val;
            x += lowbit(x);
        }
    }
    pii a[maxn];
    pii b[maxn];
    pii c[maxn];
    int n, m;
    std::vector<int> vx,vy;
    struct node {
        int op;
        int x, y;
        int k;
        int id;
        node() {}
        node(int opp, int xx, int yy, int kk, int idd)
        {
            op = opp;
            x = xx;
            y = yy;
            k = kk;
            id = idd;
        }
    } info[maxn];
    int ans[maxn];
    bool cmp(node aa, node bb)
    {
        if (aa.x != bb.x) {
            return aa.x < bb.x;
        } else if (aa.op != bb.op) {
            return aa.op < bb.op;
        } else {
            return aa.y < bb.y;
        }
    }
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        gbtb;
        cin >> n >> m;
        repd(i, 1, n) {
            cin >> a[i].fi >> a[i].se;
            vx.push_back(a[i].fi);
            vy.push_back(a[i].se);
        }
        repd(i, 1, m) {
            cin >> b[i].fi >> b[i].se >> c[i].fi >> c[i].se;
            vx.push_back(b[i].fi);
            vy.push_back(b[i].se);
            vx.push_back(c[i].fi);
            vy.push_back(c[i].se);
            vy.push_back(b[i].se - 1);
            vx.push_back(b[i].fi - 1);
        }
        sort(ALL(vx));
        sort(ALL(vy));
        vx.erase(unique(ALL(vx)),vx.end());
        vy.erase(unique(ALL(vy)),vy.end());
        my=sz(vy)+10;
        int cnt = 0;
        int dx, dy;
        repd(i, 1, n) {
            ++cnt;
            dx = lower_bound(ALL(vx), a[i].fi) - vx.begin() + 1;
            dy = lower_bound(ALL(vy), a[i].se) - vy.begin() + 1;
            info[cnt] = node(0, dx, dy, 0, 0);
        }
        repd(i, 1, m) {
            ++cnt;
            dx = lower_bound(ALL(vx), c[i].fi) - vx.begin() + 1;
            dy = lower_bound(ALL(vy), c[i].se) - vy.begin() + 1;
            info[cnt] = node(1, dx, dy, 1, i);
    
            ++cnt;
            dx = lower_bound(ALL(vx), c[i].fi) - vx.begin() + 1;
            dy = lower_bound(ALL(vy), b[i].se - 1) - vy.begin() + 1;
            info[cnt] = node(1, dx, dy, -1, i);
    
            ++cnt;
            dx = lower_bound(ALL(vx), b[i].fi - 1) - vx.begin() + 1;
            dy = lower_bound(ALL(vy), c[i].se) - vy.begin() + 1;
            info[cnt] = node(1, dx, dy, -1, i);
    
            ++cnt;
            dx = lower_bound(ALL(vx), b[i].fi-1) - vx.begin() + 1;
            dy = lower_bound(ALL(vy), b[i].se-1) - vy.begin() + 1;
            info[cnt] = node(1, dx, dy, 1, i);
    
        }
        sort(info + 1, info + 1 + cnt, cmp);
        repd(i, 1, cnt) {
            if (!info[i].op) {
                add(info[i].y, 1);
            } else {
                ans[info[i].id] += info[i].k * ask(info[i].y);
            }
        }
        repd(i, 1, m) {
            printf("%d
    ", 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/ 希望所写的文章对您有帮助。
  • 相关阅读:
    Atitit 趋势管理之道 attilax著
    Atitit 循环处理的新特性 for...else...
    Atitit 2017年的技术趋势与未来的大技术趋势
    atitit 用什么样的维度看问题.docx 如何了解 看待xxx
    atitit prj mnrs 项目中的几种经理角色.docx
    Atitit IT办公场所以及度假村以及网点以及租房点建设之道 attilax总结
    Atitit 工具选型的因素与方法 attilax总结
    Atitit.团队文化建设影响组织的的一些原理 法则 定理 效应 p826.v4
    Atiitt 管理方面的误区总结 attilax总结
    Atitit 未来趋势把控的书籍 attilax总结 v3
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11594591.html
Copyright © 2011-2022 走看看