luogu【模板】三维偏序(陌上花开)
嘟嘟嘟
很显然我开始学\(CDQ\)分治了。
我刚开始学的时候看了一篇博客,上面全是一些抽象的概念,看完后真是一头雾水,最后还不得不抄了这题的代码。
但这样可不行呀……
于是我就不打算再扣那篇博客,而是自己想,最后真的自己想明白了。
(个人感觉这道题跟\(CDQ\)分治关系不大)
首先想一下二维偏序:我们先按第一维排序,然后第二维动态的用树状数组维护。也就是说,得保证前几维都有序的前提下,才可以用数据结构维护最后一维。
现在换到了三维:所以我们必须保证在前两维有序的前提下,才能维护第三维。
首先都能想到,按第一维排序,这样就保证第一维有序了。
如何保证第二维\(y\)有序?如果硬排序,又会导致第一维\(x\)乱序。但是排序还是要排的。有没有一种排序方法能使第一维“不太乱”呢?
答案是有的:归并排序!对于区间\([L, R]\),虽然\([L, mid]\)和\([mid + 1, R]\)中的\(y\)有序,\(x\)乱序,但是\([mid + 1, R]\)中的任何一个元素的\(x\)仍是比\([L, mid]\)中的任何一个都大的!因此右区间相对于左区间保证了前两维有序,所以此时我们就能用树状数组维护第三维了!
这大概就是\(CDQ\)分治中的左修改只会对右询问造成影响的意思吧。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e5 + 5;
const int maxm = 2e5 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, m, k;
struct Node
{
int x, y, z, cnt, sum;
bool operator < (const Node& oth)const
{
if (x != oth.x) return x < oth.x;
if (y != oth.y) return y < oth.y;
return z < oth.z;
}
bool operator != (const Node& oth)const
{
return x != oth.x || y != oth.y || z != oth.z;
}
bool operator > (const Node& oth)const
{
if(y != oth.y) return y < oth.y;
return z <= oth.z;
}
}a[maxn], t[maxn];
int c[maxm];
int lowbit(int x)
{
return x & -x;
}
void init(int pos)
{
for(; pos <= k; pos += lowbit(pos))
if(c[pos] != 0) c[pos] = 0;
else break;
}
void add(int pos, int d)
{
for(; pos <= k; pos += lowbit(pos)) c[pos] += d;
}
int query(int pos)
{
int ret = 0;
for(; pos; pos -= lowbit(pos)) ret += c[pos];
return ret;
}
void cdqSolve(int L, int R)
{
if(L == R) return;
int mid = (L + R) >> 1, id1 = L, id2 = mid + 1;
cdqSolve(L, mid); cdqSolve(mid + 1, R);
for(int i = L; i <= R; ++i)
{
if(id2 > R || (id1 <= mid && a[id1] > a[id2])) //这个大于号是比较第二维的,不是真正的大于号
{
t[i] = a[id1++];
add(t[i].z, t[i].cnt);
}
else
{
t[i] = a[id2++];
t[i].sum += query(t[i].z);
}
}
for(int i = L; i <= R; ++i) a[i] = t[i], init(a[i].z);//分治的每一层,别忘了清空树状数组
}
int ans[maxn];
int main()
{
m = read(); k = read();
for(int i = 1; i <= m; ++i) t[i].x = read(), t[i].y = read(), t[i].z = read();
sort(t + 1, t + m + 1);
for(int i = 2, j = 1; i <= m + 1; ++i)
if(t[j] != t[i] || i == m + 1) a[++n] = t[j], a[n].cnt = i - j, j = i;
cdqSolve(1, n);
for(int i = 1; i <= n; ++i) ans[a[i].sum + a[i].cnt - 1] += a[i].cnt;
for(int i = 0; i < m; ++i) write(ans[i]), enter;
return 0;
}
luogu【模板】三维偏序(陌上花开)的更多相关文章
- luogu P3810 三维偏序(陌上花开)cdq分治
题目链接 思路 对一维排序后,使用$cdq$分治,以类似归并排序的方法处理的二维,对于满足$a[i].b \leq a[j].b$的点对,用树状数组维护$a[i].c$的数量.当遇到$a[i].b&g ...
- [Luogu 3810]三维偏序
Description 有 $ n $ 个元素,第 $ i $ 个元素有 $ a_i $ .$ b_i $ .$ c_i $ 三个属性,设 $ f(i) $ 表示满足 $ a_j \leq a_i $ ...
- Luogu P3810 【模板】三维偏序(陌上花开)(CDQ分治)
题目 以三维偏序为例来讲一下CDQ分治. CDQ的本质就是把一个序列分成两段,计算左边对右边的贡献,然后分治. 不过一般都是先分治到底再从下往上算,这样可以先归并再算. 比如这道题,我们先按第一维排序 ...
- P3810 【模板】三维偏序(陌上花开)
P3810 [模板]三维偏序(陌上花开) cdq分治+树状数组 三维偏序模板题 前两维用cdq分治,第三维用树状数组进行维护 就像用树状数组搞逆序对那样做--->存权值的出现次数 attenti ...
- Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治
Luogu 3810 & BZOJ 3263 陌上花开/三维偏序 | CDQ分治 题面 \(n\)个元素,每个元素有三个值:\(a_i\), \(b_i\) 和 \(c_i\).定义一个元素的 ...
- P3810 【模板】三维偏序(陌上花开)(CDQ分治)
题目背景 这是一道模板题 可以使用bitset,CDQ分治,K-DTree等方式解决. 题目描述 有 nn 个元素,第 ii 个元素有 a_iai.b_ibi.c_ici 三个属性,设 f(i) ...
- 洛谷P3810 陌上花开 CDQ分治(三维偏序)
好,这是一道三维偏序的模板题 当然没那么简单..... 首先谴责洛谷一下:可怜的陌上花开的题面被无情的消灭了: 这么好听的名字#(滑稽) 那么我们看了题面后就发现:这就是一个三维偏序.只不过ans不加 ...
- P3810 -三维偏序(陌上花开)cdq-分治
P3810 [模板]三维偏序(陌上花开) 思路 :按照 1维排序 二维 分治三维树状数组维护 #include<bits/stdc++.h> using namespace std; #d ...
- BZOJ3262:陌上花开 & 洛谷3810:三维偏序——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3262 https://www.luogu.org/problemnew/show/3810 Desc ...
- BZOJ3262 陌上花开 —— 三维偏序 CDQ分治
题目链接:https://vjudge.net/problem/HYSBZ-3262 3262: 陌上花开 Time Limit: 20 Sec Memory Limit: 256 MBSubmit ...
随机推荐
- [javaSE] 并发编程(线程间通信)
新建一个资源类Resource 定义成员变量String name 定义成员变量int age 新建一个输入类Input,实现Runnable接口 定义一个构造方法Input(),传入参数:Resou ...
- golang使用graphviz
graphviz的介绍请参考: http://www.cnblogs.com/ghj1976/p/4539788.html 安装 graphviz 需要在 http://www.graphviz.o ...
- 【 js 片段 】如何组织表单的默认提交?【亲测有效】
最近做的一个项目,我分到的部分有表单验证.点击了提交按钮,但我并不想让他跳转页面去提交.于是经过各种百度,各种 stackoverflow,各种抱大神腿之后,有了以下解决办法: 重点就是阻止 form ...
- sublime text2 注册码
近终于找到 sublime Text2 升级到 2.0.2 build 2221 64位 的破破解 输入注册码就成了 ----- BEGIN LICENSE ----- Andrew Weber S ...
- NodeJs -- express 快速建站
直接上干货 1.新建一个目录来存放我们即将要做的东西: 2.win+R打开小黑框:进入到我们的目录下: 3.首先我们要全局安装Express框架:**在这一步之前要确保你本机上安装了node:** n ...
- pair
pair的类型: pair 是 一种模版类型.每个pair 可以存储两个值.这两种值无限制.也可以将自己写的struct的对象放进去.. 功能:pair将一对值组合成一个值,这一对值可以具有不同的数据 ...
- angular2 如何使用websocket
1.npm下载: npm install angular2-websocket 2.需要在哪个组件使用就在那里引入: import {$WebSocket} from 'angular2-websoc ...
- Linux 启动脚本及chkconfig命令之自启动服务
有时我们会碰到这样的情况,系统启动的时候报一大堆无法连接mysql的错误,问题在mysql数据库还没有启动的时候已经启动了一些需要连接mysql数据库的服务.这样我们就得修改启动顺序,把需要连接mys ...
- java web项目中引入spring
自己动手实践了一次,发生中间出了一下问题,现整理出来,供参考. Step1: 新建一个java web项目 Step2:下载spring的jar包http://repo.spring.io/libs- ...
- java语言导学(5版)--第12章并发之二
1不可变对象 概念:(immutable)对象创建后,状态不可更改.不可变对象在并发程序中尤其有用,因状态不可变,不会被线程干扰,也不会出现不一致状态. 书中通过实例是可变的类,并从此类衍生出一个不可 ...