首页 > 编程语言 >算法学习-CDQ分治

算法学习-CDQ分治

时间:2024-09-19 12:02:31浏览次数:1  
标签:偏序 rua return int 分治 mid 算法 CDQ 数组

对于二维偏序,为普通的求逆序对,只需要先排序一遍,然后树状数组或双指针即可
而三位偏序甚至更高,则需要用CDQ分治,简单来说,就是将树状数组和双指针结合
操作步骤如下:

  • 1.开始将数组按第一维排序,保证满足x性质
  • 2.在归并中,将左右分别按y排序,因为开始以x排序,所以保证了正确性,保证贡献从左到右
  • 3.相当于用树状数组处理二维偏序,再用双指针合并左右两部分数组即可
#include <bits/stdc++.h>
#define int long long

using namespace std;

const int N = 200010;

int n, k;
struct rua
{
	int x, y, z;
	int res, cnt;
} a[N];
int tr[N], res[N];

bool check(int x, int y)
{
	return (a[x].x == a[y].x && a[x].y == a[y].y && a[x].z == a[y].z);
}

bool cmpx(rua x, rua y)
{
	if (x.x != y.x) return x.x < y.x;
	else if (x.y != y.y) return x.y < y.y;
	return x.z < y.z;
}

bool cmpy(rua x, rua y)
{
	if (x.y != y.y) return x.y < y.y;
	return x.z < y.z;
}

int lowbit(int x)
{
	return x & -x;
}

void update(int x, int v)
{
	for (int i = x; i <= k; i += lowbit(i)) tr[i] += v;
}

int query(int x)
{
	int res = 0;
	for (int i = x; i; i -= lowbit(i)) res += tr[i];
	return res;
}

void solve(int l, int r)
{
	if (l == r) return;
	int mid = l + r >> 1;
	solve(l, mid), solve(mid + 1, r);
	sort(a + l, a + mid + 1, cmpy);
	sort(a + mid + 1, a + r + 1, cmpy);
	int i = mid + 1, j = l;
	while (i <= r)
	{
		while (a[j].y <= a[i].y && j <= mid) update(a[j].z, a[j].cnt), j ++ ;
		a[i].res += query(a[i].z);
		i ++ ;
	}
	for (int i = l; i < j; i ++ ) update(a[i].z, -a[i].cnt);
}

signed main()
{
	cin >> n >> k;
	for (int i = 1; i <= n; i ++ ) cin >> a[i].x >> a[i].y >> a[i].z;
	
	sort(a + 1, a + 1 + n, cmpx);
//	for (int i = 1; i <= n; i ++ ) cout << a[i].x << ' ' << a[i].y << ' ' << a[i].z << '\n';
	int cnt = 0;
	for (int i = 1; i <= n; i ++ )
	{
		int j = i + 1;
		while (check(i, j)) j ++ ;
		j -- ;
		a[ ++ cnt] = {a[i].x, a[i].y, a[i].z, 0, j - i + 1};
		i = j;
	}
//	for (int i = 1; i <= n; i ++ )
//		cout << a[i].cnt << ' ';
//	cout << '\n';
	
	solve(1, n);
	
	for (int i = 1; i <= n; i ++ ) res[a[i].res + a[i].cnt - 1] += a[i].cnt;
	
	for (int i = 0; i < n; i ++ ) cout << res[i] << '\n';
	
	return 0;
}

标签:偏序,rua,return,int,分治,mid,算法,CDQ,数组
From: https://www.cnblogs.com/MafuyuQWQ/p/18420327

相关文章

  • 【算法】堆与优先级队列
    【ps】本篇有4道 leetcode OJ。目录一、算法简介二、相关例题1)最后一块石头的重量.1-题目解析.2-代码编写2)数据流中的第K大元素.1-题目解析.2-代码编写3)前K个高频单词.1-题目解析.2-代码编写4)数据流的中位数.1-题目解析.2-代码编写 一、算......
  • 多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测
    多输入多输出|Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测目录多输入多输出|Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料预测效果基本介绍多输入多输出|Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入......
  • 一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention
    一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention目录一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention效果一览基本介绍程序设计参考资料效果一览基本介绍1.Matlab实现RIME-BiTCN-BiGRU-Attention霜冰算法优化双向时间卷积双向门控循环......
  • 顶刊算法 | Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变
    顶刊算法|Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测,优化前后对比目录顶刊算法|Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测,优化前后对比预测效果基本介绍程序设计参考资料预测效果基本......
  • CNN-SVM模型 | Matlab实现SO-CNN-SVM蛇群算法优化卷积神经网络结合支持向量机多特征分
    CNN-SVM模型|Matlab实现SO-CNN-SVM蛇群算法优化卷积神经网络结合支持向量机多特征分类预测目录CNN-SVM模型|Matlab实现SO-CNN-SVM蛇群算法优化卷积神经网络结合支持向量机多特征分类预测分类效果基本描述程序设计参考资料分类效果基本描述1.Matlab实现SO-CNN-SVM蛇群算法优化......
  • 【开题报告+背景+源码】基于过滤协同算法苗族银饰推荐系统的设计与实现
    项目背景与意义课题苗族银饰推荐系统,应用Java技术设计开发一个苗族银饰推荐系统,实现用户购买苗族银饰商品方便快捷,不受时间和空间的限制功能,提供用户能够更快更好地获取自己想要的苗族银饰商品推荐服务,达到向消费者提供商品推荐,帮助他们发现感兴趣的苗族银饰商品并增加购买意......
  • 基于档案演化路径的快速收敛EO多目标优化算法及其在工程设计问题中的应用
    目录1.摘要2.基于档案演化路径机制的快速收敛多目标平衡优化算法(FC‑MOEO/AEP)2.1单目标平衡优化算法EO2.2多目标平衡优化算法FC‑MOEO/AEP3.结果展示4.参考文献5.代码获取1.摘要在实际的工程优化问题中,耗时的目标函数是不可避免的。这类函数使得元启发式方法......
  • 算法:动态规划思路(仅作记录)
    以leetcode70题爬楼梯为例:假设你正在爬楼梯。需要n阶你才能到达楼顶。每次你可以爬1或2个台阶。你有多少种不同的方法可以爬到楼顶呢?递归一共两种爬楼梯的方式如果最后一步要用到方法1,那么我们得先爬到n−1,要解决的问题缩小成:从0爬到n−1有多少种不同的方法。......
  • 自动驾驶运动规划学习_碰撞检测算法_GJK
    自动驾驶运动规划学习:碰撞检测算法:GJKGilbert–Johnson–Keerthi(GJK)算法,是一种用于检测两个凸集是否重叠的高效算法,并且可以得到两个凸集的最小距离.1.4.1 GJK算法原理1.4.1.1 闵可夫斯基差(Minkowski Difference)1.4.1.3 凸性在二维空间中,如果一个凸集包含原......
  • Dijkstra 算法
    普通堆实现的Dijkstra算法时间复杂度为O(m*logm),m为边数distance[i]表示从源点到i点的最短距离,visited[i]表示i节点是否从小根堆弹出过准备好小根堆,小根堆存放记录:(x点,源点到x的距离),小根堆根据距离排序令distance[源点]=0,(源点,0)入堆从小根堆弹出(u......