(暂时没有vjudge题面,CF的题面又太丑2333,直接口述了)
题目大意:给你一个长度为n的序列a[],和一个数x,对于每个i= 0~n ,求有多少个子区间满足恰好有i个数<x。
sol: 这不是FFT的套路题吗2333,直接做<的0/1前缀和,然后
记录到cnt里直接卷一遍就好了2333.
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<vector>
#include<complex>
#define ll long long
using namespace std;
#define D double
#define E complex<double>
const int maxn=530005;
const D pi=acos(-1);
int n,N,l,r[maxn],X,cnt[maxn],A[maxn];
E a[maxn],b[maxn];
ll ans[maxn];
inline int read(){
int x=0,f=1; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x*f;
}
void W(ll x){ if(x>=10) W(x/10); putchar(x%10+'0');}
inline void FFT(E *c,int F){
for(int i=0;i<N;i++) if(i<r[i]) swap(c[i],c[r[i]]);
for(int i=1;i<N;i<<=1){
E omega(cos(pi/i),F*sin(pi/i));
for(int P=i<<1,j=0;j<N;j+=P){
E now(1,0);
for(int k=0;k<i;k++,now*=omega){
E x=c[j+k],y=c[j+k+i]*now;
c[j+k]=x+y;
c[j+k+i]=x-y;
}
}
}
if(F==-1) for(int i=0;i<N;i++) a[i]/=N;
}
inline void build(){
for(int i=0;i<=n;i++) a[i]=b[n-i]=cnt[i];
for(N=1;N<=(n<<1);N<<=1) l++;
for(int i=0;i<N;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
inline void solve(){
FFT(a,1),FFT(b,1);
for(int i=0;i<N;i++) a[i]*=b[i];
FFT(a,-1);
ans[0]=(ll)(floor(a[n].real()+0.5)-n)>>1;
for(int i=1;i<=n;i++) ans[i]=(ll)floor(a[n+i].real()+0.5);
}
int main(){
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
n=read(),X=read(),cnt[0]++;
for(int i=1;i<=n;i++){
A[i]=A[i-1]+(read()<X);
cnt[A[i]]++;
}
build();
solve();
for(int i=0;i<=n;i++) W(ans[i]),putchar(' ');
return 0;
}