首页 > 其他分享 >cdq分治

cdq分治

时间:2024-08-13 18:05:57浏览次数:9  
标签:偏序 ch int 分治 消掉 cdq 一维

我觉得呢,cdq的本质就是在归并排序消掉一维的影响来处理多维偏序问题。既然本质跟二分有关,那很容易猜到cdq处理k维偏序的时间复杂度为\(O(Nlog^{k-1}N)\)

三维偏序问题:形如:$求满足条件a_i<a_j,b_i<b_j,c_i<c_j且 \(j !=i\) 的 j 个数

比较常考的就是三维偏序,一般做法就是sort消掉一维的影响,cdq消掉一维的影响,在用树状数组维护前缀和来完成。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int N=1e6+107;
int n,k;
int b[N],s[N],f[N];
int read()
{
	int f=1,s=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
	return f*s;
}


struct lmy
{
	int x,y,z,id;
}a[N];

bool comp1(lmy a,lmy b)
{
	if(a.x!=b.x) return a.x<b.x;
	if(a.y!=b.y) return a.y<b.y;
	return a.z<b.z;
}
bool comp2(lmy a,lmy b)
{
	if(a.y!=b.y) return a.y<b.y;
	if(a.z!=b.z) return a.z<b.z;
	return a.x<b.x;
}
struct tree_array
{
	int c[N];
	int lowbit(int x){return x&(-x);}
	void add(int x,int val)
	{
		while(x<=k)
		{
			c[x]+=val;
			x+=lowbit(x);
		}
	}
	int sum(int x)
	{
		int ans=0;
		while(x)
		{
			ans+=c[x];
			x-=lowbit(x);
		}
		return ans;
	}
}Q;
void cdq(int l,int r)
{
	if(l==r) return ;
	int mid=(l+r)>>1;
	cdq(l,mid); cdq(mid+1,r);
	sort(a+l,a+r+1,comp2);
	for(int i=l;i<=r;i++)
	{
		if(a[i].x<=mid) Q.add(a[i].z,1);
		else s[a[i].id]+=Q.sum(a[i].z);
	}
	for(int i=l;i<=r;i++) if(a[i].x<=mid) Q.add(a[i].z,-1);
}
int main()
{
	n=read(),k=read();
	for(int i=1;i<=n;i++)
	{
		a[i].x=read(),a[i].y=read(),a[i].z=read();
		a[i].id=i;
	}
	sort(a+1,a+1+n,comp1);
	int i=1;
	while(i<=n)
	{
		int j=i+1;
		while(j<=n&&a[j].x==a[i].x&&a[j].y==a[i].y&&a[j].z==a[i].z)
			j++;
		while(i<j) 
			b[a[i].id]=a[j-1].id,i++;
	}
	for(int i=1;i<=n;i++) a[i].x=i;
	cdq(1,n);
	for(int i=1;i<=n;i++) f[s[b[a[i].id]]]++;
	for(int i=0;i<n;i++) printf("%d\n",f[i]);
}

至于更多维的偏序问题,我们就可以cdq套cdq套cdq……

标签:偏序,ch,int,分治,消掉,cdq,一维
From: https://www.cnblogs.com/zhengchenxi/p/18357478

相关文章

  • CDQ分治
    P3810【模板】三维偏序(陌上花开)CDQ模板题,考虑先按\(a\)排序,减掉一位,然后再\(CDQ\)分治一维,用树状数组维护最后一维还有本题特殊,去重操作不要忘记点击查看代码#include<bits/stdc++.h>#definespeed()ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);#definell......
  • CDQ分治
    CDQ分治的思想最早由IOI2008金牌得主陈丹琦在高中时整理并总结,它也因此得名。CDQ分治的思想常用于离线解决点对之间的问题,最经典的如三维偏序。解决这类问题的过程为:将序列$(l,r)$分为。递归处理序列$(l,mid)$和$(mid+1,r)$中的答案。设计算法处理......
  • cdq分治总结
    \(cdq\)分治是一种离线分治算法,可以将动态问题改变为静态问题,不适用于强制在线。其实现时通常将需要进行的操作存进一个结构体,然后对这些操作进行分治。打\(cdq\)分治时一个直观的感受就是很好想思路,但就是不知道怎么打。。。它一共有三个需要干的1找到范围中点\(mid\)......
  • 【CDQ分治】三元环
    三元环HDU-7439思路考虑\(3\)个点的有向图,要么成环,要么有一个点入度为\(2\),假设第个点的入度为\(d_i\),答案为\(C_n^3-\sum\limits_{i=1}^nC_{d_i}^2\)。根据题目关系,\(i\rightarrowj\)当且仅当\(i<j\and\f_i<f_j\and\g_i<g_j\),否则就是\(j\rightarrowi......
  • 【CDQ分治】【模板】三维偏序(陌上花开)
    P3810【模板】三维偏序(陌上花开)-洛谷|计算机科学教育新生态(luogu.com.cn)#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;template<typenameT>structBIT{#ifndeflowbit#definelowbit(x)(x&(-x));#endifintn;vector<T&......
  • 【CDQ分治】[P5094 [USACO04OPEN] MooFest G 加强版
    P5094[USACO04OPEN]MooFestG加强版-洛谷|计算机科学教育新生态(luogu.com.cn)#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intn;cin>>n;vecto......
  • [算法] 一些分治
    普通分治其实没啥,每次只计算跨越分治中心的区间的贡献,剩下的递归到左右两边进行分治;时间复杂度:分治树高度为$\Theta(\logn)$,乘上其他操作的复杂度即可;例题一:现在有一个$n$阶排列$a$,计算:\[\sum^{n}_{i=1}\sum^{n}_{j=i}\min(a_i,a_{i+1},...,a_j)\]......
  • 20240806:点分治,虚树选做
    POJ-1741Tree题意:给定一棵树,求多少无序对\((u,v)\)满足\(\text{dist}(u,v)\lek\)。对于树上的路径进行分类:经过根;不经过根。第二类路径点可以通过递归子树求出。对于经过根的路径,可以一遍dfs求出每个点到根的距离\(\text{dis}(u)\)。问题转化为求\(\text{dis}(u)......
  • CDQ分治
    CDQ分治CDQ分治是一种思想而不是具体的算法,与动态规划类似。目前这个思想的拓展十分广泛,依原理与写法的不同,大致分为三类:解决和点对有关的问题。1D动态规划的优化与转移。通过CDQ分治,将一些动态问题转化为静态问题。解决和点对有关的问题这类问题多数类似于「给定一......
  • 根号分治(待补充)
    最近有根号分治的题都没那么熟悉,想到了方向感也很差,故写一点题解。LCA查询看到题目中的条件\(\sumk\le10^5\)说明\(k\leS\)的个数很多,\(S\lek\)的个数很少。那么对于前者,考虑一开始最朴素的\(O(S^2)\)的暴力,枚举集合中的两个点,求\(LCA\)总时间复杂度\(O(\fra......