CF993E Nikita and Order Statistics
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF993E Nikita and Order Statistics相关的知识,希望对你有一定的参考价值。
CF993E Nikita and Order Statistics
题意:
给你一个数组
a
1
∼
n
a_1 \\sim n
a1∼n,对于
k
=
0
∼
n
k = 0 \\sim n
k=0∼n,求出有多少个数组上的区间满足:区间内恰好有 k 个数比 x 小。 x 为一个给定的数。
n
≤
2
×
1
0
5
n \\le 2 \\times 10^5
n≤2×105
−
1
e
9
<
=
a
i
<
=
1
e
9
-1e9<=a_i<=1e9
−1e9<=ai<=1e9
题解:
因为x是常数,也就是说对于每个数只有贡献和无贡献之分
所以我们把所有大于等于X的数都改为0,小于X的数都改为1,这样原问题就转化为问有多少个连续序列满足和为k
用公式表示就是:
∑
i
=
1
n
∑
j
=
1
n
[
a
i
−
a
j
=
k
]
\\sum_i=1^n\\sum_j=1^n[a_i-a_j=k]
∑i=1n∑j=1n[ai−aj=k]
设前缀和
s
u
m
i
=
∑
j
=
1
i
a
j
sum_i=\\sum_j=1^ia_j
sumi=∑j=1iaj
再设
S
i
=
∑
[
s
u
m
j
=
i
]
,
S
0
=
0
S_i=\\sum[sum_j=i],S_0=0
Si=∑[sumj=i],S0=0,
S
i
S_i
Si就表示前缀和等于i的数量
原问题就变成求:
∑
i
=
k
+
1
n
S
i
⋅
S
i
−
k
\\sum_i=k+1^nS_i⋅S_i-k
i=k+1∑nSi⋅Si−k
比如k=2时,我们要查询区间和等于2的数量,答案就是区间前缀和等于3的数量乘以区间和等于1的数量,前缀和等于4的数量乘以前缀和等于2的数量…。因为前缀和等于3的减去前缀和等于1得到的这段区间一定是等于2的,因此可以这样转化
这个式子看着愈发熟悉。。好像是卷积,卷起来
∑
i
=
k
+
1
n
S
i
⋅
S
i
−
k
=
∑
i
−
j
=
k
S
i
⋅
S
j
=
∑
i
+
j
=
k
S
i
⋅
S
−
j
=
∑
i
+
j
=
n
+
k
S
i
⋅
S
n
−
j
\\sum_i=k+1^nS_i⋅S_i-k=\\sum_i-j=kS_i⋅S_j=\\sum_i+j=kS_i⋅S_-j=\\sum_i+j=n+kS_i⋅S_n-j
i=k+1∑nSi⋅Si−k=i−j=k∑Si⋅Sj=i+j=k∑Si⋅S−j=i+j=n+k∑Si⋅Sn−j
答案就是n+k的系数,k=0时要特判
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI=acos(-1.0);
struct Complex
double x,y;
Complex(double _x=0.0,double _y=0.0)
x=_x;
y=_y;
Complex operator -(const Complex &b)const
return Complex(x-b.x,y-b.y);
Complex operator +(const Complex &b)const
return Complex(x+b.x,y+b.y);
Complex operator *(const Complex &b)const
return Complex(x*b.x-y*b.y,x*b.y+y*b.x);
;
void change(Complex y[],int len)
int i,j,k;
for(i=1,j=len/2;i<len-1;i++)
if(i<j) swap(y[i],y[j]);
k=len/2;
while(j>=k)
j-=k;
k/=2;
if(j<k)j+=k;
void fft(Complex y[],int len,int on)
change(y,len);
for(int h=2;h<=len;h<<=1)
Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for(int j=0;j<len;j+=h)
Complex w(1,0);
for(int k=j;k<j+h/2;k++)
Complex u=y[k];
Complex t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn;
if(on==-1)
for(int i=0;i<len;i++)
y[i].x/=len;
const int MAXN=800010;
Complex x1[MAXN],x2[MAXN];
int str1[MAXN/2],str2[MAXN/2],a[MAXN];
ll sum[MAXN];
int _sum[MAXN];
int t,n,x;
int main()
scanf("%d%d",&n,&x);
memset(str1,0,sizeof str1);
memset(str2,0,sizeof str2);
str1[0]=1;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
if(a[i]<x)a[i]=1;
else a[i]=0;
_sum[i]=_sum[i-1]+a[i];
str1[_sum[i]]+=1;
for(int i=0;i<=n;i++)
str2[i]=str1[n-i];
int len=1,len1=n+1,len2=n+1;
while(len<len1*2||len<len2*2) len<<=1;
for(int i=0;i<len1;i++)
x1[i]=Complex(str1[i],0);
for(int i=len1;i<len;i++)
x1[i]=Complex(0,0);
for(int i=0;i<len2;i++)
x2[i]=Complex(str2[i],0);
for(int i=len2;i<len;i++)
x2[i]=Complex(0,0);
// for(int i=0;i<len;i++)
// cout<<x2[i].x<<" ";
//
// cout<<endl;
// cout<<"--"<<endl;
// for(int i=0;i<len;i++)
// cout<<str2[i]<<" ";
// cout<<endl;
fft(x1,len,1);
fft(x2,len,1);
for(int i=0;i<len;i++)
x1[i]=x1[i]*x2[i];
// for(int i=0;i<len;i++)
// cout<<"x1[i]="<<x1[i].x<<endl;
// cout<<endl;
fft(x1,len,-1);
ll ans=0,num=0;
for(int i=1;i<=n+1;i++)
if(a[i以上是关于CF993E Nikita and Order Statistics的主要内容,如果未能解决你的问题,请参考以下文章
CF993E Nikita and Order Statistics
CF993E Nikita and Order Statistics
CF993E Nikita and Order Statistics