1. 程式人生 > 其它 >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;
}