洛谷 P2804 神秘数字
题目大意:n个数,求有多少个连续区间和平均值大于m.
n个数先都减掉m,然后算一遍前缀和,那么就是要找多少个区间和大于0.
转化为s[j]-s[i]>0即s[j]>s[i](j>i),那么就是求顺序对了.
由于出现负数难以离散化,所以还是用归并排序倒过来求逆序对,效率nlogn。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <queue> 7 #include <map> 8 #define ll long long 9 #define out(a) printf("%d",a) 10 #define writeln printf("\n") 11 #define N 200050 12 using namespace std; 13 int n,m; 14 int b[N]; 15 ll ans,a[N],sum[N],num[N]; 16 int read() 17 { 18 int s=0,t=1; char c; 19 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 20 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 21 return s*t; 22 } 23 ll readl() 24 { 25 ll s=0,t=1; char c; 26 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 27 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 28 return s*t; 29 } 30 void mergesort(int l,int r) 31 { 32 if (l==r) return; 33 int mid=(l+r)>>1; 34 mergesort(l,mid); mergesort(mid+1,r); 35 int x=l,y=mid+1,tot=l; 36 while (x<=mid&&y<=r){ 37 if (a[x]<=a[y]) num[tot++]=a[x++]; 38 else { 39 num[tot++]=a[y++]; 40 ans+=mid-x+1; 41 } 42 } 43 while (x<=mid) 44 num[tot++]=a[x++]; 45 while (y<=r) 46 num[tot++]=a[y++]; 47 for (int i=l;i<=r;i++) 48 a[i]=num[i]; 49 } 50 int main() 51 { 52 n=read(); ans=0; m=read(); 53 for (int i=1;i<=n;i++) 54 b[i]=read(),b[i]-=m; 55 for (int i=1;i<=n;i++) 56 sum[i]=sum[i-1]+b[i]; 57 for (int i=1;i<=n+1;i++) 58 a[i]=sum[n-i+1]; 59 mergesort(1,n+1); 60 ans%=92084931; 61 out(ans); 62 return 0; 63 }