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

    P3810 【模板】三维偏序(陌上花开)

    声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。

    题目描述

    (n) 个元素,第 (i) 个元素有 (a_i,b_i,c_i) 三个属性,设 (f(i)) 表示满足 (a_j leq a_i)(b_j leq b_i)(c_j leq c_i)(j e i)(j) 的数量。

    对于 (d in [0, n)),求 (f(i) = d) 的数量。

    (\)


    (\)

    (Solution)

    这道题和树状数组那道一样

    这里的 (a) 可以看做树状数组里的时间,只不过那里的操作是有序的,所以这道题第一步是把 (a) 排个序,当做 (CDQ) 的时间

    然后 (b) 和那道题的位置一样,于是也可以归并排序balabala

    但是还有一个 (c) ,我们可以用一个树状数组维护,累计答案就可!

    完结

    然而这道题有非常多的坑点...

    (1.)对于相等的三元组,要把它们合并,并且要存它们的数量,在树状数组累计的时候加的应该是那个三元组的数量,最后统计答案,每个三元组还得加上数量 (-1) ,因为相等也算答案(关于为什么树状数组不用判相等,因为每个操作的时间是唯一的,所以不可能有相等的)

    (2.)排序的时候如果 (a) 不相等则按 (a) 的大小排,如果 (a) 相等再按 (b) 的大小排,还相等再按 (c) 的大小排,不然计算答案会出错

    (3.)由于每次都要清空树状数组,虽然照理来说是跑满 (O(nlog{n}))(10^7) 可以过来着,但是被卡了...重新开一个数组记录被修改过的树状数组,清空就快一些

    完结撒花✿✿ヽ(°▽°)ノ✿

    (\)


    (\)

    (Code)

    #include<bits/stdc++.h>
    #define mid ((l + r) >> 1)
    #define lowbit(x) x & -x
    #define F(i, x, y) for(int i = x; i <= y; ++ i)
    using namespace std;
    int read();
    const int N = 1e5 + 5;
    const int M = 2e5 + 5;
    int n, k, m, cnt;
    int tree[M], f[N], d[N], s[N], vis[M];
    struct node{
    	int a, b, c, num, w;
    }p[N], tmp[N];
    bool cmp(node x, node y)
    {
    	if(x.a != y.a) return x.a < y.a;
    	if(x.b != y.b) return x.b < y.b;
    	return x.c < y.c;
    }
    void add(int pos, int v){for(; pos <= m; pos += lowbit(pos)) {tree[pos] += v; if(! vis[pos]) s[++ s[0]] = pos, vis[pos] = 1;}}
    int getans(int pos){int res = 0; for(; pos; pos -= lowbit(pos)) res += tree[pos]; return res;}
    void CDQ(int l, int r)
    {
    	if(l == r) return;
    	CDQ(l, mid), CDQ(mid + 1, r);
    	int i = l, j = mid + 1, o = l - 1;
    	while(i <= mid && j <= r)
    		if(p[i].b < p[j].b || p[i].b == p[j].b && p[i].c <= p[j].c)
    			add(p[i].c, p[i].w), tmp[++ o] = p[i ++];
    		else f[p[j].num] += getans(p[j].c), tmp[++ o] = p[j ++];
    	while(i <= mid) tmp[++ o] = p[i ++];
    	while(j <= r) f[p[j].num] += getans(p[j].c), tmp[++ o] = p[j ++];
    	F(i, 1, s[0]) tree[s[i]] = 0, vis[s[i]] = 0; s[0] = 0;
    	F(i, l, r) p[i] = tmp[i];
    }
    int main()
    {
    	n = read(), m = read();
    	F(i, 1, n) p[i].a = read(), p[i].b = read(), p[i].c = read();
    	sort(p + 1, p + 1 + n, cmp);
    	F(i, 1, n) 
    	{
    		++ k;
    		if(p[i].a != p[i + 1].a || p[i].b != p[i + 1].b || p[i].c != p[i + 1].c)
    			tmp[++ cnt] = p[i], tmp[cnt].num = cnt, tmp[cnt].w = k, k = 0;
    	}
    	F(i, 1, cnt) p[i] = tmp[i];
    	CDQ(1, cnt);
    	F(i, 1, cnt) d[f[p[i].num] + p[i].w - 1] += p[i].w;
    	F(i, 0, n - 1) printf("%d
    ", d[i]);
    	return 0;
    }
    int read()
    {
    	int x = 0;
    	char c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x;
    }
    
  • 相关阅读:
    linux杀死僵尸进程
    通过dd命令显示硬盘的读写性能
    linux 压缩与解压缩
    linux云主机cpu一直很高降不下来,系统日志报nf_conntrack: table full, dropping packet.
    vsftp配置文件详解
    linux中ping带时间及打印内容到文件
    atop工具检测linux硬件异常
    windows连接服务端的域名正常,linux却不通,(针对于负载均衡后端节点设置)
    有你的地方就是天堂
    Java 异常 —— java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible
  • 原文地址:https://www.cnblogs.com/Bn_ff/p/12845605.html
Copyright © 2011-2022 走看看