【复赛模拟试题】新斯诺克 逆序对
来源:互联网 发布:淘宝超级快车好用吗 编辑:程序博客网 时间:2024/04/27 14:59
【问题描述】
考虑这样一种新斯诺克,设母球(母球即是白球,用于击打其他球)的标号为m,台面上有 N 个红球排成一排,每一个红球都有一个标号,他们的标号代表了他们的分数。现在用母球击打这些红球,一杆击打,如果母球接触到红球,就称为“K到红球”。我们假设,一次可以击打任意多相邻连续的红球,也可以只击打一个球。并且红球既不会落袋,也不会相互发生碰撞,而只是停留在原处。每次击打时候,要想“K到红球”,至少要击打一个红球,如果想一次击打多个红球,那么击打的红球必须是依次连续排列的。如果一次 “K到红球”所有红球的标号之和的平均数大于母球的标号m,就获得了一个 “连击”。现在给定你一个局面,请你计算总共能有多少种“连击”方案。
例如当前有4个红球排成一排,它们的标号依次为3, 7, 2, 4,母球标号为m=3, 则有如下 7 种“连击”方案: (7)、(4)、(3,7)、(7,2)、(3,7,2)、(7,4,2)、(3,7,2,4)。因为(3)和(2,4)中红球标号的平均值不大于3,所以它们不是合法的“连击”方案。
【输入格式】
输入共有两行,第一行是 n m,n 表示台面上一共有 n 个红球,m 表示母球的标号。第二行是 n 个正整数,依次表示台面上 n 个红球的标号。所有标号均不超过2*10^9。
【输出格式】
输出只有一个数,为“连击”的方案总数。
【输入样例】
4 3
3 7 2 4
【输出样例】
7
【数据范围】
30%的数据满足:n≤1000
100%的数据满足: n<=100000, m<=10^9
——————————————————————————————————————————————
暴力没问题,转化一下就发现可以把上面的连击描述成一个新的数组(A[i]-M)的前缀和数组的逆序对。
时间复杂度O(nlogn)
给出各种解法的代码(暴力、归并排序、树状数组)。注意一下求逆序对的时候前缀和里面一定要多放一个0进去,因为这个前缀和只要大于0就是合法的。
AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<map>#include<vector>#include<cctype>using namespace std;typedef long long LL;const int maxn=100005;int N,M,num[maxn];LL ans,sum[maxn],tmp[maxn];LL A[maxn],B[maxn];int C[maxn],MAX;void _scanf(int &x){ x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();}void data_in(){ _scanf(N);_scanf(M); for(int i=1;i<=N;i++) _scanf(num[i]);}void work30()//对于每个球,向右枚举以这个球为起点的连续区间。 { for(int i=1;i<=N;i++) { LL now=0; for(int j=i;j<=N;j++) { now+=num[j]; if((LL)M*(j-i+1)<now) ans++; } } cout<<ans<<endl;}LL msort(int L,int R,LL *a)//从大到小排序 { if(R-L<=1) return 0; int m=L+R>>1; LL t1=msort(L,m,a); LL t2=msort(m,R,a); LL t3=0; int i=L,j=m,cnt=L; while(i<m&&j<R) { if(a[i]<a[j]) tmp[cnt++]=a[j++],t3+=m-i; else tmp[cnt++]=a[i++]; } while(i<m) tmp[cnt++]=a[i++]; while(j<R) tmp[cnt++]=a[j++]; for(int k=L;k<R;k++) a[k]=tmp[k]; return t1+t2+t3;}void work100_1(){ for(int i=1;i<=N;i++) sum[i]=sum[i-1]+num[i]-M; ans=msort(0,N+1,sum); cout<<ans<<endl;}void LSH(LL *a){ memcpy(B,sum,sizeof(B)); sort(B,B+N+1); int cnt=unique(B,B+N+1)-B; for(int i=0;i<=N;i++) { A[i]=lower_bound(B,B+cnt+1,sum[i])-B+1; if(A[i]>MAX) MAX=A[i]; }}int lowbit(int i) { return i&(-i); }int add(int i){ LL re=0; while(i>0) re+=C[i],i-=lowbit(i); return re;}void update(int i,int d){ while(i<=MAX) C[i]+=d,i+=lowbit(i);}void work100_2(){ for(int i=1;i<=N;i++) sum[i]=sum[i-1]+num[i]-M; LSH(sum); for(int i=0;i<=N;i++) { ans+=add(A[i]-1); update(A[i],1); } cout<<ans<<endl;}int main(){ freopen("snooker.in","r",stdin); freopen("snooker.out","w",stdout); data_in();// work30(); work100_1();// work100_2(); return 0;}
- 【复赛模拟试题】新斯诺克 逆序对
- 【基础练习】【归并逆序对】codevs3324 新斯诺克题解
- 【复赛模拟试题】求和
- 【复赛模拟试题】收费站
- 【复赛模拟试题】河床
- 新斯诺克
- 新斯诺克
- 【复赛模拟试题】计数排序
- 【复赛模拟试题】 物品选取
- 【复赛模拟试题】学生公寓 贪心
- 【复赛模拟试题】书的排序
- 【复赛模拟试题】盛夏的果实
- 【复赛模拟试题】寿司 中位数思想
- 【复赛模拟试题】奶牛卧室 筛法
- Codevs P3324 新斯诺克
- Codevs3324 新斯诺克
- 【u249】新斯诺克
- Codevs 3324 新斯诺克
- JSP基础(七)——JSP的9个内置对象
- 9.23 未来的规划 BEC
- PHP 超全局变量,表单处理
- JSP(Java Server Page)
- 一种可行性Java爬虫框架
- 【复赛模拟试题】新斯诺克 逆序对
- C#学习笔记9-指数参数params
- 动态内存开辟--new_delete和malloc_free(十八)
- opencv学习笔记 一 载入、显示和保存图像
- vertical-align 属性设置元素的垂直对齐方式。
- 欢迎使用CSDN-markdown编辑器
- 统计学简介之十三——两个总体参数的检验
- 011 复合函数的极限运算法则
- Mac 下matplotlib中文乱码问题