Luogu 3810 & BZOJ 3263 陌上花开/三维偏序 | CDQ分治

题面

\(n\)个元素,每个元素有三个值:\(a_i\), \(b_i\) 和 \(c_i\)。定义一个元素的偏序是三个值都小于等于它的值的元素的个数,对于\([0, n)\)的每个值\(i\),求偏序为\(i\)的元素个数。

题解

这道题我使用的是CDQ分治

这道题有三个维度,每个维度都要对应一个数据结构/算法,来逐个击破。

首先,按照\(a\)从小到大把所有元素排序,保证\(a\)从小到大。

然后,对于第二维进行分治:首先对mid两边的子区间分别处理,然后处理左边子区间内的元素对有边子区间内元素的贡献。

处理跨mid贡献,我们需要使用树状数组。把左右两个子区间分别按照\(b\)排序,对于右边的每个元素,先把左边所有b比它小、尚未加入树状数组的元素加入树状数组,即树状数组中左区间当前元素的\(c\)的对应位值上的值增加;然后计算右区间当前元素的\(c\)的对应位置的前缀和,把右区间当前元素的答案加上这个前缀和。

需要注意:

数据中有些元素是完全相同的,做的时候要去重,把原来的相同元素的个数当做新的唯一元素的权值。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define space putchar(' ')
#define enter putchar('\n')
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
} const int N = 2000005;
int n, k, tot, tr[N], ans[N];
struct mem{
int a, b, c, cnt, sum;
bool operator < (const mem &B) const{
if(a != B.a) return a < B.a;
if(b != B.b) return b < B.b;
return c < B.c;
}
bool operator == (const mem &B) const{
return a == B.a && b == B.b && c == B.c;
}
} m[N], t[N];
bool cmp(const mem &A, const mem &B){
return A.b < B.b;
}
void add(int p, int x){
while(p <= k) tr[p] += x, p += p & -p;
}
int ask(int p){
int ret = 0;
while(p) ret += tr[p], p -= p & -p;
return ret;
}
void solve(int l, int r){
if(l == r) return;
int mid = (l + r) >> 1;
solve(l, mid), solve(mid + 1, r);
sort(m + l, m + mid + 1, cmp);
sort(m + mid + 1, m + r + 1, cmp);
int pl = l, pr = mid + 1;
while(pr <= r){
while(pl <= mid && m[pl].b <= m[pr].b)
add(m[pl].c, m[pl].cnt), pl++;
m[pr].sum += ask(m[pr].c);
pr++;
}
for(int i = l; i < pl; i++)
add(m[i].c, -m[i].cnt);
}
int main(){
read(n), read(k), tot = n;
for(int i = 1, a, b, c; i <= n; i++)
read(a), read(b), read(c), t[i] = (mem){a, b, c, 0, 0};
sort(t + 1, t + n + 1);
n = 0;
for(int i = 1; i <= tot; i++){
if(i == 1 || !(t[i] == t[i - 1]))
m[++n] = t[i];
m[n].cnt++;
}
solve(1, n);
for(int i = 1; i <= n; i++)
ans[m[i].sum + m[i].cnt - 1] += m[i].cnt;
for(int i = 0; i < tot; i++)
write(ans[i]), enter;
return 0;
}

Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治的更多相关文章

  1. BZOJ 3262 陌上花开 (三维偏序CDQ+树状数组)

    题目大意: 题面传送门 三维偏序裸题 首先,把三元组关于$a_{i}$排序 然后开始$CDQ$分治,回溯后按$b_{i}$排序 现在要处理左侧对右侧的影响了,显然现在左侧三元组的$a_{i}$都小于等 ...

  2. BZOJ3262 陌上花开 —— 三维偏序 CDQ分治

    题目链接:https://vjudge.net/problem/HYSBZ-3262 3262: 陌上花开 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit ...

  3. bzoj3262: 陌上花开 三维偏序cdq分治

    三维偏序裸题,cdq分治时,左侧的x一定比右侧x小,然后分别按y排序,对于左侧元素按y大小把z依次插入到树状数组里,其中维护每个左侧元素对右侧元素的贡献,在bit查询即可 /************* ...

  4. [bzoj] 3263 陌上花开 洛谷 P3810 三维偏序|| CDQ分治 && CDQ分治讲解

    原题 定义一个点比另一个点大为当且仅当这个点的三个值分别大于等于另一个点的三个值.每比一个点大就为加一等级,求每个等级的点的数量. 显然的三维偏序问题,CDQ的板子题. CDQ分治: CDQ分治是一种 ...

  5. BZOJ 2141 排队 (三维偏序CDQ+树状数组)

    题目大意:略 洛谷传送门 和 [CQOI2015]动态逆序对 这道题一样的思路 一开始的序列视为$n$次插入操作 把每次交换操作看成四次操作,删除$x$,删除$y$,加入$x$,加入$y$ 把每次操作 ...

  6. BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 题意:简单明了. 思路:终于好像有点明白CDQ分治处理三维偏序了.把删除操作看作是插入操作,那 ...

  7. 三维偏序[cdq分治学习笔记]

    三维偏序 就是让第一维有序 然后归并+树状数组求两维 cdq+cdq不会 告辞 #include <bits/stdc++.h> // #define int long long #def ...

  8. BZOJ3262/Luogu3810 陌上花开 (三维偏序,CDQ)

    一个下午的光阴之死,凶手是细节与手残. 致命的一枪:BIT存权值时: for(; x <= maxx; x += x&-x) t[x] += w; //for(; x <= n; ...

  9. 洛谷P3810-陌上开花(三维偏序, CDQ, 树状数组)

    链接: https://www.luogu.org/problem/P3810#submit 题意: 一个元素三个属性, x, y, z, 给定求f(b) = {ax <= bx, ay < ...

随机推荐

  1. oracle数据库更改字符集

    在数据迁徙的时候需要使源和目标数据库的字符集.版本等信息统一…… 这里是对一个数据库的设置,需要在两边进行同样的操作. SYS@PROD1> select userenv('language') ...

  2. 402. Remove K Digits/738.Monotone Increasing Digits/321. Create Maximum Number

    Given a non-negative integer num represented as a string, remove k digits from the number so that th ...

  3. golang slice使用不慎导致的问题

    原文链接 : http://www.bugclosed.com/post/16 背景 go语言中切片slice是方便且好用的强大数据结构,但是使用的时候需要注意,不然容易出问题,最近因为遇到了一个sl ...

  4. 网页调起App之应用实践

    声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场.举报 新春佳节即将到来,北京的上地&西二旗.望京&国贸.五道口&中关村地区等程序员 ...

  5. DWR、Comet4j在Nginx+Tomcat组合下的优化

    DWR.Comet4j这类推送框架在Tomcat下运行正常,但在nginx+tomcat组合下,可能会出现断连.延迟等各种问题. 如出现此类问题,可尝试以下优化方式: 1.Nginx-----ngin ...

  6. jdbc连接获取表名称

    1,Class.forName可以替换为mysql之类其他的数据库驱动 public Connection connect(String url,String username,String pw, ...

  7. iOS开发学习-类似微信聊天消息中的电话号码点击保存到通讯录中的功能

    类似微信聊天消息中的电话号码点击保存到通讯录中的功能,ABAddress的实现在iOS9中是不能正常使用的,点击完成后,手机会非常的卡,iOS9之后需要使用Contact新提供的方法来实现该功能.快捷 ...

  8. shiro+springmvc 都使用缓存

    基于涛哥shiro案例16 的这时候要配置service方法的缓存 在spring-config.xml添加 <context:annotation-config /> <cache ...

  9. js数组遍历 千万不要使用for...in...

    昨天做个下拉框 扩充了一下数组的方法 Array.prototype.remove = function (val) { var index = this.indexOf(val); if (inde ...

  10. CentOS下Neo4j安装教程

    本文记录一下在CentOS 6.7上,安装neo4j图数据库,本文安装的版本为neo4j-community-2.3.9-unix.tar.gz. 下载Neo4j安装包 使用wget命令获取Neo4j ...