zoukankan      html  css  js  c++  java
  • 10.16T6 逆序对变式

    Description

      斯诺克又称英式台球,是一种流行的台球运动。在球桌上,台面四角以及两长边中心位置各有一个球洞,使用的球分别为1个白球,15个红球和6个彩球(黄、绿、棕、蓝、粉红、黑)共22个球。击球顺序为一个红球、一个彩球直到红球全部落袋,然后以黄、绿、棕、蓝、粉红、黑的顺序逐个击球,最后以得分高者为胜。斯诺克的魅力还在于可以打防守球,可以制造一些障碍球使对方无法击打目标球而被扣分。正是因为这样,斯诺克是一项充满神奇的运动。
      现在考虑这样一种新斯诺克,设母球(母球即是白球,用于击打其他球)的标号为M,台面上有N个红球排成一排,每一个红球都有一个标号,他们的标号代表了他们的分数。
      现在用母球击打这些红球,一杆击打,如果母球接触到红球,就称为“K到红球”。我们假设,一次可以击打任意多相邻连续的红球,也可以只击打一个球。
      并且红球既不会落袋,也不会相互发生碰撞,而只是停留在原处。每次击打时候,要想“K到红球”,至少要击打一个红球,如果想一次击打多个红球,那么击打的红球必须是依次连续排列的。
      如果一次“K到红球”所有红球的标号之和的平均数大于母球的标号M,就获得了一个“连击”。
      现在请你计算总共能有多少种“连击”方案。
      注意:如果当前有标号为1、2、3的三种红球,母球标号为0,有如下6种获得“连击”方:(1)、(2)、(3)、(12)、(2,3)、(1,2,3)

    Input

      输入文件sheeta.in共有两行,第一行是N,M(N<=100000,M<=10000),N表示台面上一共有N个红球,M表示母球的标号。
      第二行是N个正整数,依次表示台面上N个红球的标号,所有标号均不超过10000。

    Output

      输出文件sheeta.out只有一个数,为“连击”的方案总数。

    Sample Input

    4 3
    3 7 2 4

    Sample Output

    7
     
    跟官方题解有些出入
    由于我们是求平均值,所以我们读入的时候把每一个数字都减去m,然后求前缀和
    接着我们的任务就是求多少个区间值是正数
    也就是sum[j]>sum[i]同时 j>i 显然就是一个逆序对
    鉴于不想写归并排序,我就离散化了一下解决了
    最后被long long略卡了一下
    code:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 #define N 1000005
     6 long long c[N+1],sum[N],n,m,a[N]; 
     7 long long lowbit(long long x){
     8     return x&(-x);
     9 }
    10 void add(long long x,long long v){
    11     while(x<=N){
    12         c[x]+=v;
    13         x+=lowbit(x);
    14     }
    15 }
    16 long long query(long long x){
    17     long long ans=0;
    18     while(x){
    19         ans+=c[x];
    20         x-=lowbit(x); 
    21     }
    22     return ans;
    23 }
    24 long long d[N],cnt;
    25 int main(){
    26     cin>>n>>m;
    27     for(long long i=1;i<=n;i++){
    28         cin>>a[i];
    29         a[i]-=m;
    30         sum[i]=sum[i-1]+a[i];
    31         d[++cnt]=sum[i];
    32     }
    33     d[++cnt]=0;
    34     sort(d+1,d+cnt+1);
    35     for(long long i=1;i<=n;i++){
    36         sum[i]=lower_bound(d+1,d+cnt+1,sum[i])-d;
    37     //    cout<<sum[i]<<" ";
    38     } 
    39     sum[0]=lower_bound(d+1,d+cnt+1,0)-d;
    40     long long ans=0;
    41     for(long long i=0;i<=n;i++){
    42         ans+=query(sum[i]);
    43         add(sum[i]+1,1);
    44     }
    45     cout<<ans;
    46     return 0;
    47 }

    over

  • 相关阅读:
    C语言中返回字符串函数的四种实现方法
    (转)大整数除法jva.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result异常的解决方法
    @Transactional使用try->catch捕获异常并回滚方法
    Golang1.13.x 解决go get 无法下载问题
    Zookeeper:Unable to read additional data from client sessionid 0x00, likely client has closed socket
    解决Linux系统下面javamelody图片中文乱码问题
    mybatis查询mysql的datetime类型数据时间差了14小时
    以太坊多重钱包离线签名
    Solidity智能合约如何判断地址为0或空
    Solidity开发注意
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9800539.html
Copyright © 2011-2022 走看看