• LA4329 Ping pong 树状数组


    题意:
    一条大街上住着n个乒乓球爱好者,经常组织比赛切磋技术。每个人都有一个能力值a[i]。
    每场比赛需要三个人:两名选手,一名裁判。他们有个奇怪的约定,裁判必须住在两名选手之间,而裁判的能力值也必须在两名选手之间。
    问一共能组织多少种比赛。

    分析:
    考虑第i个人,假设a1到ai-1中有ci个比ai小,那么就有(i-1)-ci个比ai大;
    同理,如果ai+1到an中有di个比ai小,那么就有(n-i)-di个比ai大。
    i当裁判就有:ci * (n-i-di) + (i-1-ci)*di种比赛。

    然后问题就转化为了计算数组c和数组d。这样的话就很容易想到使用树状数组去计算前缀和。
     1 #include<iostream>
     2 #include<string>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cstdio>
     6 #include<set>
     7 #include<map>
     8 #include<vector>
     9 #include<cstring>
    10 #include<stack>
    11 #include<cmath>
    12 #include<queue>
    13 #include <bits/stdc++.h>
    14 using namespace std;
    15 #define INF 0x3f3f3f3f
    16 #define ll long long
    17 #define clc(a,b) memset(a,b,sizeof(a))
    18 
    19 inline int lowbit(int x)
    20 {
    21     return x&-x;
    22 }
    23 
    24 struct bit
    25 {
    26     int n;
    27     vector<int>C;
    28 
    29     void resise(int n)
    30     {
    31         this->n=n;
    32         C.resize(n);
    33     }
    34     void clear()
    35     {
    36         fill(C.begin(),C.end(),0);
    37     }
    38     int sum(int x)
    39     {
    40         int ret=0;
    41         while(x>0)
    42         {
    43             ret+=C[x];
    44             x-=lowbit(x);
    45         }
    46         return ret;
    47     }
    48     void add(int x,int d)
    49     {
    50         while(x<=n)
    51         {
    52             C[x]+=d;
    53             x+=lowbit(x);
    54         }
    55     }
    56 };
    57 
    58 const int maxn=20000+5;
    59 int n,a[maxn],c[maxn],d[maxn];
    60 
    61 bit f;
    62 
    63 int main()
    64 {
    65     int t;
    66     scanf("%d",&t);
    67     while(t--)
    68     {
    69         scanf("%d",&n);
    70         int maxa=0;
    71         for(int i=1; i<=n; i++)
    72         {
    73             scanf("%d",&a[i]);
    74             maxa=max(maxa,a[i]);
    75         }
    76         f.resise(maxa);
    77         f.clear();
    78         for(int i=1; i<=n; i++)
    79         {
    80             f.add(a[i],1);
    81             c[i]=f.sum(a[i]-1);
    82         }
    83         f.clear();
    84         for(int i=n; i>=1; i--)
    85         {
    86             f.add(a[i],1);
    87             d[i]=f.sum(a[i]-1);
    88         }
    89         ll ans=0;
    90         for(int i=1; i<=n; i++)
    91             ans+=(ll)c[i]*(n-i-d[i])+(ll)d[i]*(i-c[i]-1);
    92         printf("%lld
    ",ans);
    93     }
    94     return 0;
    95 }
    View Code
  • 相关阅读:
    洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk( 普及-)
    洛谷 P1909 [NOIP2016 普及组] 买铅笔
    全排列问题
    集合的划分(setsub)
    自然数拆分-回溯
    洛谷 P4414 [COCI2006-2007#2] ABC
    洛谷 P5709 【深基2.习6】Apples Prologue
    洛谷 P4326 [COCI2006-2007#1] Herman
    平面分割
    洛谷 P1601 A+B Problem(高精)
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5189309.html
Copyright © 2020-2023  润新知