P5459 [BJOI2016]回转寿司 cdq分治

时间:2021-07-20
本文章向大家介绍P5459 [BJOI2016]回转寿司 cdq分治,主要包括P5459 [BJOI2016]回转寿司 cdq分治使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

P5459 [BJOI2016]回转寿司

不会cdq的看这里:cdq分治:从分治到套娃

转化为求 j<i,L<=sum[i]-sum[j-1]<=R的对数的问题,其中sum为前缀和

经典的三维偏序,当然也可以分治后排序再用队列来维护。

你也可以试试直接用数据结构来做(话说cdq不就是把数据结构转成了归并排序来做的嘛)

#include<algorithm>
#include<iostream>
#include<cstdio>
#define LL long long 
using namespace std;
int n;
LL L,R,ans;
const int N=100005;
LL sum[N],tmp[N];
void cdq(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq(l,mid);cdq(mid+1,r);
	int head=l,tail=l-1;
	for(int i=mid+1;i<=r;++i)
	{
		while(tail+1<=mid&&sum[i]-sum[tail+1]>=L)++tail;
		while(head<=mid&&sum[i]-sum[head]>R)++head;
		ans+=tail-head+1;
	}
//	下面的过程相当于sort(sum+l,sum+r+1); 但用时不一样 
	int now=l,i=l,j=mid+1;
	while(i<=mid&&j<=r)
		if(sum[i]<=sum[j])tmp[now]=sum[i],++now,++i;
		else tmp[now]=sum[j],++now,++j;
	for(;i<=mid;++i)tmp[now]=sum[i],++now;
	for(;j<=r;++j)tmp[now]=sum[j],++now;
	for(int i=l;i<=r;++i)sum[i]=tmp[i];
}
int main()
{
	cin>>n>>L>>R;
	for(int i=1,x;i<=n;++i)scanf("%d",&x),sum[i]=sum[i-1]+x;
	cdq(0,n);cout<<ans;
	return 0;
}

原文地址:https://www.cnblogs.com/wljss/p/14966138.html