hdu 2443 Counter Strike

    技术2022-05-19  28

    是一道好题

    设s[0]=0,sum[i]=s[0]+s[1]+...s[i]

    那么对于一个可行区间[i,j],

    (sum[j]-sum[i-1])/(j-i+1)>a <=> sum[j]-sum[i-1]>a*(j-i+1)

       <=> sum[j]-sum[i-1]-a*(j-i+1)>0

       <=> s[j]-a+s[j-1]-a+...+s[i]-a>0

    令s'[i]=s[i]-a,则sum'[i]=sum[i]-i*a

    那么(sum[j]-sum[i-1])/(j-i+1)>a <=> sum'[j]-sum'[i]>0

     <=> sum'[i]<sum'[j] i<j

    意思就是把一段区间的平均值大于a转化成先把每个数减去a,然后这个区间的和大于0

     

    这样,我们只要求有多少对sum'[i]和sum'[j]满足上述条件就行了,跟求逆序对数 差不多

    注意答案要用__int64保存

     

    代码:

    #include<iostream> #include<cstdio> #include<memory.h> using namespace std; const int MAX=100005; int s[MAX],h[MAX]; int n,a; __int64 ans; void merge(int l,int m,int r) { int i=l,j=m+1,k=l; while(i<=m&&j<=r) { if(s[i]<s[j]) { ans+=r-j+1; h[k++]=s[i++]; } else { h[k++]=s[j++]; } } while(i<=m) h[k++]=s[i++]; while(j<=r) h[k++]=s[j++]; for(i=l;i<=r;i++) s[i]=h[i]; } void mergesort(int l,int r) { int m=(l+r)/2; if(l<r) { mergesort(l,m); mergesort(m+1,r); merge(l,m,r); } } int main() { int i,j,T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&a); s[0]=0; ans=0; for(i=1;i<=n;i++) { scanf("%d",&j); j-=a; s[i]=s[i-1]+j; } mergesort(0,n); cout<<ans<<endl; } return 0; } 


    最新回复(0)