日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CF993E Nikita and Order Statistics

發布時間:2023/12/3 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CF993E Nikita and Order Statistics 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CF993E Nikita and Order Statistics

題意:

給你一個數組 a1~na_{1 \sim n}a1n?,對于 k=0~nk = 0 \sim nk=0n,求出有多少個數組上的區間滿足:區間內恰好有 k 個數比 x 小。 x 為一個給定的數。
n≤2×105n \le 2 \times 10^5n2×105
?1e9<=ai<=1e9-1e9<=a_i<=1e9?1e9<=ai?<=1e9

題解:

因為x是常數,也就是說對于每個數只有貢獻和無貢獻之分
所以我們把所有大于等于X的數都改為0,小于X的數都改為1,這樣原問題就轉化為問有多少個連續序列滿足和為k
用公式表示就是:∑i=1n∑j=1n[ai?aj=k]\sum_{i=1}^n\sum_{j=1}^n[a_i-a_j=k]i=1n?j=1n?[ai??aj?=k]
設前綴和sumi=∑j=1iajsum_i=\sum_{j=1}^ia_jsumi?=j=1i?aj?
再設Si=∑[sumj=i],S0=0S_i=\sum[sum_j=i],S_0=0Si?=[sumj?=i],S0?=0,SiS_iSi?就表示前綴和等于i的數量
原問題就變成求:∑i=k+1nSi?Si?k\sum_{i=k+1}^nS_i?S_{i-k}i=k+1n?Si??Si?k?
比如k=2時,我們要查詢區間和等于2的數量,答案就是區間前綴和等于3的數量乘以區間和等于1的數量,前綴和等于4的數量乘以前綴和等于2的數量…。因為前綴和等于3的減去前綴和等于1得到的這段區間一定是等于2的,因此可以這樣轉化
這個式子看著愈發熟悉。。好像是卷積,卷起來
∑i=k+1nSi?Si?k=∑i?j=kSi?Sj=∑i+j=kSi?S?j=∑i+j=n+kSi?Sn?j\sum_{i=k+1}^nS_i?S_{i-k}=\sum_{i-j=k}S_i?S_{j}=\sum_{i+j=k}S_i?S_{-j}=\sum_{i+j=n+k}S_i?S_{n-j}i=k+1n?Si??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]==0&&i!=n+1)num++;else {ans+=num*(num+1)/2;num=0; } }cout<<ans<<" ";// cout<<endl;for(int i=1;i<=n;i++){cout<<(ll)(x1[i+n].x+0.5)<<" ";}return 0; }

總結

以上是生活随笔為你收集整理的CF993E Nikita and Order Statistics的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。