CodeForces - 993E Nikita and Order Statistics
(暂时没有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; }
我爱学习,学习使我快乐