洛谷 P2804 神秘数字

洛谷 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("
")
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 }
View Code
原文地址:https://www.cnblogs.com/Kaleidoscope233/p/9340585.html