有注释CDQ分治求助
查看原帖
有注释CDQ分治求助
195331
Mine_KingCattleya楼主2021/10/12 21:49

只搞到了 30pts 求助
我的思路:先统计所有sum>=L的子串数量ansL和sum<=R的子串数量ansR,然后结果为ansL+ansR-n*(n+1)/2。
思路大概没问题,可是代码萎了,求大佬帮忙查错

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,L,R;
long long ansL,ansR,a[100005],b[100005],cpy[100005];
void merge(int l,int r)//归并排序
{
	int mid=(l+r)/2;
	int tot=l,i=mid+1,j=l;
	for(;i<=r;i++)
	{
		while(j<=mid&&a[i]>=a[j-1]) b[tot++]=a[j++];
		b[tot++]=a[i];
	}
	while(j<=mid) b[tot++]=a[j++];
	for(int k=l;k<=r;k++) a[k]=b[k];
	return ;
}
void CDQ1(int l,int r)//求ansL
{
	if(l==r) return ;
	int mid=(l+r)/2;
	CDQ1(l,mid),CDQ1(mid+1,r);
	int i=mid+1,j=l;
	for(;i<=r;i++)
	{
		while(j<=mid&&a[i]-a[j-1]>=L) j++;
		ansL+=j-l;
	}
	merge(l,r);
	return ;
}
void CDQ2(int l,int r)//求ansR
{
	if(l==r) return ;
	int mid=(l+r)/2;
	CDQ2(l,mid),CDQ2(mid+1,r);
	int i=mid+1,j=l;
	for(;i<=r;i++)
	{
		while(j<=mid&&a[i]-a[j-1]>R) j++;
		ansR+=mid-j+1;
	}
	merge(l,r);
	return ;
}
int main()
{
	scanf("%d%d%d",&n,&L,&R);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		if(a[i]>=L) ansL++;
		if(a[i]<=R) ansR++;
		a[i]+=a[i-1];
	}
	memcpy(cpy,a,sizeof cpy);
	CDQ1(1,n);
	memcpy(a,cpy,sizeof a);
	CDQ2(1,n);
	printf("%lld\n",ansL+ansR-1ll*n*(n+1)/2);
	return 0;
}

求大佬帮忙查错或hack数据
感激不尽>_<

2021/10/12 21:49
加载中...