zoukankan      html  css  js  c++  java
  • Day6

    很久很久以前,在遥远的大陆上有一个美丽的国家。统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草。有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……” “那么本质上它是一个深度优先搜索,陛下”,园丁深深地向国王鞠了一躬。 “嗯……我听说有一种怪物叫九头蛇,它非常贪吃苹果树……” “是的,显然这是一道经典的动态规划题,早在N元4002年我们就已经发现了其中的奥秘了,陛下”。 “该死的,你究竟是什么来头?” “陛下息怒,干我们的这行经常莫名其妙地被问到和OI有关的题目,我也是为了预防万一啊!” 王者的尊严受到了伤害,这是不可容忍的。看来一般的难题是难不倒这位园丁的,国王最后打算用车轮战来消耗他的实力: “年轻人,在我的花园里的每一棵树可以用一个整数坐标来表示,一会儿,我的骑士们会来轮番询问你某一个矩阵内有多少树,如果你不能立即答对,你就准备走人吧!”说完,国王气呼呼地先走了。 这下轮到园丁傻眼了,他没有准备过这样的问题。所幸的是,作为“全国园丁保护联盟”的会长——你,可以成为他的最后一根救命稻草。Input第一行有两个整数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)为右上坐标。Output共输出m行,每行一个整数,即回答国王以(aj,bj)和(cj,dj)为界的矩形里有多少棵树。Sample Input3 1 0 0 0 1 1 0 0 0 1 1

    Sample Output3

    思路:统计区间个数,想到二维树状数组,但数据太大无法开下,就选择离散化+偏序一维树状数组来进行二维树状数组的操作,将询问拆成4部分,就像二维树状数组一样

    using namespace std;
    #define lowbit(x) ((x)&(-x))
    typedef long long LL;
    
    const int maxm = 5e5+5;
    
    int x[maxm], y[maxm], a[maxm], b[maxm], c[maxm], d[maxm], n, m, tot, C[maxm], ally[maxm], ans[maxm][5];
    
    void add(int pos, int val) {
        for(; pos <= tot; pos += lowbit(pos))
            C[pos] += val;
    }
    
    int getsum(int pos) {
        int ret = 0;
        for(; pos; pos -= lowbit(pos))
            ret += C[pos];
        return ret;
    }
    
    struct Node {
        int x, y, id, val;
        Node(){}
        bool operator<(const Node &a) const {
            return x < a.x || (x == a.x && val < a.val);
        }
    } Nodes[maxm*5];
    
    int main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) {
            scanf("%d%d", &x[i], &y[i]);
            ally[++tot] = y[i];
        }
        for(int i = 1; i <= m; ++i) {
            scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
            ally[++tot] = b[i], ally[++tot] = d[i];
        }
        sort(ally+1, ally+tot+1);
        int len = unique(ally+1, ally+tot+1)-ally-1;
        int nodesum = 0;
        for(int i = 1; i <= n; ++i) {
            Nodes[nodesum].x = x[i], Nodes[nodesum++].y = lower_bound(ally+1, ally+1+len, y[i]) - ally;
        }
        for(int i = 1; i <= m; ++i) {
            int ty1 = lower_bound(ally+1, ally+1+len, d[i]) - ally, ty2 = lower_bound(ally+1, ally+1+len, b[i]) - ally;
            Nodes[nodesum].x = c[i], Nodes[nodesum].y = ty1, Nodes[nodesum].id = i, Nodes[nodesum++].val = 1;
            Nodes[nodesum].x = a[i]-1, Nodes[nodesum].y = ty1, Nodes[nodesum].id = i, Nodes[nodesum++].val = 2;
            Nodes[nodesum].x = c[i], Nodes[nodesum].y = ty2-1, Nodes[nodesum].id = i, Nodes[nodesum++].val = 3;
            Nodes[nodesum].x = a[i]-1, Nodes[nodesum].y = ty2-1, Nodes[nodesum].id = i, Nodes[nodesum++].val = 4;
        }
        sort(Nodes, Nodes+nodesum);
        for(int i = 0; i < nodesum; ++i) {
            if(!Nodes[i].val) {
                add(Nodes[i].y, 1);
            } else {
                ans[Nodes[i].id][Nodes[i].val] = getsum(Nodes[i].y);
            }
        }
        for(int i = 1; i <= m; ++i)
            printf("%d
    ", ans[i][1] - ans[i][2] - ans[i][3] + ans[i][4]);
        return 0;
    }
    View Code

    补:

    这就是二维偏序问题,定一个序就变成一维统计问题,像CDQ分治也是,三维定一个序,变成二维问题,用CDQ,借助树状数组求和,本题x定序后,每一次求和都是0-x, 0-y,运用容斥拆成四个点,就无须再树状数组考虑x,只考虑y了

  • 相关阅读:
    宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/GRedComeT/p/12191580.html
Copyright © 2011-2022 走看看