zoukankan      html  css  js  c++  java
  • 洛谷 P3810 【模板】三维偏序(陌上花开) 题解

    一、题目:

    洛谷原题

    二、思路:

    很明显这是一道CDQ分治的模板题。在这里简单讲一下CDQ分治的大概思路。

    CDQ分治的目的是将动态的修改、查询离线,从而转化为静态的操作。具体来说是这样的:

    假设(a)是一个修改、查询的序列。定义(CDQ(l,r))为处理(a[lsim r])的函数。

    然后我们发现(a[lsim r])的修改和查询分别可以分成两类。

    修改 查询
    处于[l,mid]的 处于[l,mid]的
    处于[mid+1,r]$的 处于[l,mid]的

    我们发现对于一个查询(a[x]),可以看成是(a[1sim (x-1)])内的所有修改操作叠加起来造成的一个“影响”。那么我们在求解(CDQ(l,r))的时候,可以先处理(CDQ(l, mid)),再处理(CDQ(mid+1,r))

    现在我们来看一看(CDQ(l,r))的求解情况。

    类别 处于[l,mid]的修改 处于[mid+1,r]的修改
    处于[l,mid]的查询 已完成 ——
    处于[mid+1,r]的查询 未完成 已完成

    接下来的问题就是如何处理([l,mid])的修改对([r,mid+1])的查询造成的影响,可以使用其他算法解决,只要该算法的时间复杂度和区间长度有关。

    对于本题来说,我习惯将本题的(a)称为(x)(b)称为(y)(c)称为(z)

    先别考虑坐标相同的情况。一开始就按(x)坐标排序,这时候,每新加一个点就相当于先查询一次,再操作一次。我们于是就可以采用CDQ分治。

    那么究竟如何处理([l,mid])的修改对([r,mid+1])的查询造成的影响呢?可以用树状数组等数据结构,在这里不是我们强调的重点,详见代码。

    三、代码:

    //P3810
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    #define LL long long
    #define mem(s, v) memset(s, v, sizeof s)
    #define FILEIN(s) freopen(s".in", "r", stdin)
    #define FILEOUT(s) freopen(s".out", "w", stdout)
    
    inline int read(void) {
        int x = 0, f = 1; char ch = getchar();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
        while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
        return f * x;
    }
    
    const int maxn = 1e5 + 5, maxm = 2e5 + 5;
    
    int n, K, cnt, ans[maxn];
    
    struct Node {
        int x, y, z;
        int v, ans, tag, id;
        Node() { ans = tag = v = x = y = z = 0; }
        inline friend bool operator == (const Node &a, const Node &b) {
            return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
        }
    }a[maxn], t[maxn];
    
    inline bool cmp1(const Node &a, const Node &b) {
        if (a.x != b.x) return a.x < b.x;
        if (a.y != b.y) return a.y < b.y;
        return a.z < b.z;
    }
    
    inline bool cmp2(const Node &a, const Node &b) {
    	if (a.y != b.y) return a.y < b.y;
    	if (a.tag != b.tag) return a.tag < b.tag;
    	return a.id < b.id;
    }
    
    inline int lowbit(int x) { return x & (-x); }
    
    int tr[maxm];
    
    inline void add(int p, int x) {
        for (; p <= K; p += lowbit(p)) tr[p] += x;
    }
    
    inline int query(int p) {
        int ret = 0;
        for (; p; p -= lowbit(p)) ret += tr[p];
        return ret;
    }
    
    void CDQ(int l, int r) {
        if (l == r) return;
        int mid = (l + r) >> 1;
        CDQ(l, mid); CDQ(mid + 1, r);
        for (register int i = l; i <= r; ++i) a[i].id = i;
        for (register int i = l; i <= mid; ++i) a[i].tag = 0;
        for (register int i = mid + 1; i <= r; ++i) a[i].tag = 1;
        sort(a + l, a + r + 1, cmp2);
        for (register int i = l; i <= r; ++i) {
        	if (!a[i].tag) add(a[i].z, a[i].v);
        	else a[i].ans += query(a[i].z);
    	}
    	for (register int i = l; i <= r; ++i) if (!a[i].tag) add(a[i].z, -a[i].v);
    }
    
    int main() {
        n = read(); K = read();
        for (register int i = 1; i <= n; ++i) {
            a[i].x = read(); a[i].y = read(); a[i].z = read();
            a[i].v = 1;
        }
        sort(a + 1, a + n + 1, cmp1);
        cnt = 1;
        for (register int i = 2; i <= n; ++i) {
            if (a[i] == a[cnt]) ++a[cnt].v;
            else a[++cnt] = a[i]; 
        }
    /*
    在这里想说一下坐标相同的情况。事实上当x坐标相同的情况发生的时候,我们唯一担心的是区间[mid+1,r]的修改对区间[l,mid]的查询造成影响。
    但是不用担心,我们按照x为第一关键字,y为第二关键字,z为第三关键字排序,可以避免这种情况的发生。
    只有一种情况需要特别注意,那就是x、y、z都相同的时候。所以我们对这种点进行压缩处理,就OK啦!
    */
        CDQ(1, cnt);
        for (register int i = 1; i <= cnt; ++i) ans[a[i].ans + a[i].v - 1] += a[i].v;
        for (register int i = 0; i < n; ++i) printf("%d
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    纯JS实现中国行政区域上下联动选择地址
    java解析中国行政区域并在页面显示实现动态逐级筛选
    使用HttpClient 发送get、post请求,及其解析xml返回数据
    JS实现动态提示文本框可输入剩余字数(类似发表微博数字提示)
    webApi 数据绑定 获取
    EF Code First 常用命令
    [解决WebClient或HttpWebRequest首次连接缓慢问题]
    【转】Entity Framework技术系列之7:LINQ to Entities
    Ajax方法提交整个表单的信息
    【转】MVC中处理Json和JS中处理Json对象
  • 原文地址:https://www.cnblogs.com/little-aztl/p/14240270.html
Copyright © 2011-2022 走看看