P5459 [BJOI2016]回轉壽司 cdq分治
阿新 • • 發佈:2021-07-20
不會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; }