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/ 希望所写的文章对您有帮助。
  • 相关阅读:
    使用Xcode和Instruments调试解决iOS内存泄露(转载) sansan
    GCD介绍(二): 多核心的性能(转载) sansan
    iphone 常用的<app>info.plist设置(转载) sansan
    GCD介绍(一): 基本概念和Dispatch Queue (转载) sansan
    iOS 证书与签名 解惑详解[转] sansan
    Xcode快捷键 sansan
    GCD介绍(三): Dispatch Sources(转载) sansan
    Apple开发者授权 sansan
    MFC中Spin control的使用
    c++ windows mobile中设置菜单活动与否
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11594591.html
Copyright © 2011-2022 走看看