Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治
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分治的更多相关文章
- BZOJ 3262 陌上花开 (三维偏序CDQ+树状数组)
题目大意: 题面传送门 三维偏序裸题 首先,把三元组关于$a_{i}$排序 然后开始$CDQ$分治,回溯后按$b_{i}$排序 现在要处理左侧对右侧的影响了,显然现在左侧三元组的$a_{i}$都小于等 ...
- BZOJ3262 陌上花开 —— 三维偏序 CDQ分治
题目链接:https://vjudge.net/problem/HYSBZ-3262 3262: 陌上花开 Time Limit: 20 Sec Memory Limit: 256 MBSubmit ...
- bzoj3262: 陌上花开 三维偏序cdq分治
三维偏序裸题,cdq分治时,左侧的x一定比右侧x小,然后分别按y排序,对于左侧元素按y大小把z依次插入到树状数组里,其中维护每个左侧元素对右侧元素的贡献,在bit查询即可 /************* ...
- [bzoj] 3263 陌上花开 洛谷 P3810 三维偏序|| CDQ分治 && CDQ分治讲解
原题 定义一个点比另一个点大为当且仅当这个点的三个值分别大于等于另一个点的三个值.每比一个点大就为加一等级,求每个等级的点的数量. 显然的三维偏序问题,CDQ的板子题. CDQ分治: CDQ分治是一种 ...
- BZOJ 2141 排队 (三维偏序CDQ+树状数组)
题目大意:略 洛谷传送门 和 [CQOI2015]动态逆序对 这道题一样的思路 一开始的序列视为$n$次插入操作 把每次交换操作看成四次操作,删除$x$,删除$y$,加入$x$,加入$y$ 把每次操作 ...
- BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=3295 题意:简单明了. 思路:终于好像有点明白CDQ分治处理三维偏序了.把删除操作看作是插入操作,那 ...
- 三维偏序[cdq分治学习笔记]
三维偏序 就是让第一维有序 然后归并+树状数组求两维 cdq+cdq不会 告辞 #include <bits/stdc++.h> // #define int long long #def ...
- BZOJ3262/Luogu3810 陌上花开 (三维偏序,CDQ)
一个下午的光阴之死,凶手是细节与手残. 致命的一枪:BIT存权值时: for(; x <= maxx; x += x&-x) t[x] += w; //for(; x <= n; ...
- 洛谷P3810-陌上开花(三维偏序, CDQ, 树状数组)
链接: https://www.luogu.org/problem/P3810#submit 题意: 一个元素三个属性, x, y, z, 给定求f(b) = {ax <= bx, ay < ...
随机推荐
- python类与对象的组合与继承
1.把类的对象实例化放到一个新的类里面叫做类的组合,组合就是指几个横向关系的类放在一起,纵向关系的类放在一起是继承,根据实际应用场景确定.简单的说,组合用于“有一个”的场景中,继承用于“是一个”的场景 ...
- 小强版之无码理解C语言指针
1. 先从普通变量开始 2. 撸完变量撸指针 3. 故事情节进一步发展,此处少儿不宜 4. 奶茶妹妹捉奸,小强死定了 5. 源码欣赏 #include <stdio.h> ...
- jar包、war包
JavaSE程序可以打包成Jar包(J其实可以理解为Java了),而JavaWeb程序可以打包成war包(w其实可以理解为Web了).然后把war发布到Tomcat的webapps目录下,Tomcat ...
- windows离线补丁包下载路径-云盾安骑士
我们有一台阿里云服务器,只有内网可以访问,无外网资源. 阿里云账户邮箱反复收到阿里云云盾的漏洞报警通知,推荐安装安骑士组件. 安骑士组件是收费服务.阿里云服务器,无法连上外网,无法自动安装补丁.需要将 ...
- 切换nPar或vPar的启动模式
在EFI Shell中执行vparconfig即可随意切换vpar和npar模式 该命令在\EFI\HPUX目录下 vparconfig 显示当前的模式 vparconfig reboo ...
- BugPhobia准备篇章:Beta阶段前后端接口文档
0x00:序言 Two strangers fell in love, Only one knows it wasn’t by chance. To the searching tags, you m ...
- Scrum Meeting 10.24
成员 已完成任务 下一阶段任务 用时 徐越 阅读后端代码,了解服务器的概念,以及服务器和终端间的通信机制 学习服务器配置 4h 赵庶宏 阅读后端代码,了解服务器的概念,以及服务器和终端间的通信机制 阅 ...
- No.1000_第五次团队会议
光辉的一夜 今夜注定是不平凡的一夜.是崔强同学伟大的一夜. 昨天因为实验室项目,我刚上完编译课就被学院叫走去做项目,当时我就很无奈,因为说好了要和崔强一起实现下午的前端,他写界面我写底层逻辑,这样我们 ...
- BeanUtils解决日期问题
ConvertUtils.register(new DateLocaleConverter(), Date.class); BeanUtils.populate(user, request.getPa ...
- Beta 冲刺1
队名:日不落战队 安琪(队长) 过去两天完成了那些任务 修改个人信息界面. 修改手写涂鸦界面. 接下来的任务 改进手写涂鸦,加入其他功能. 还剩下的任务 社交模块功能. 遇到的困难 无. 有哪些收获和 ...