LA 4329 Ping pong (树状数组)

题意:从左到右给你n个不同的数值,让你找出三个数值满足中间的数值在两边的数值之间的个数。

析:题意还是比较好理解的,关键是怎么求数量,首先我们分解一下只有两种情况,一个是左边<中间<右边,另一种是左边>中间>右边(因为数值都不相同嘛)。

我们考虑第i个数值在中间的情况。假设a1到ai-1中有ci个比ai小的,那么就有(i-1)-ci个比ai大的(因为不包括第i个数)。同理,假设有ai+1到an中有di个比ai小,那么有(n-i)-di个比ai大,那么一共就有ci(n-i-di) + (i-ci-1)di种。问题就转化为求ci和di。

ci可以这样计算:从左到右扫描所有的ai,令x[j]表示目前为止已经考虑过的所有的ai中是否存在一个ai=j(x[j] = 1表示存在, x[j] = 0表示不存在),则ci就是前缀和x[1]+x[2]+...+x[ai-1]。初始时所有x[i]=0,在计算ci时,要先设x[ai]=1;然后求前缀和。说到这就很明显是一个数状数组的题了。利用数状数组求前缀和时间复杂度低。在O(nlogr)(r为ai的上限)时间内可计算出ci。同理可计算出di。总是时间复杂度是O(n)。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int maxn = 100000 + 10;
int sum[maxn], n, a[maxn], x[maxn], y[maxn];

int lowbit(int x){
    return x & (-x);
}

int getsum(int i){
    int s = 0;
    while(i > 0){
        s += sum[i];
        i -= lowbit(i);
    }
    return s;
}

void add(int i){
    while(i < maxn){
        ++sum[i];
        i += lowbit(i);
    }
    return ;
}

int main(){
    int T;   cin >> T;
    while(T--){
        scanf("%d", &n);
        memset(sum, 0, sizeof(sum));
        for(int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);

        for(int i = 1; i <= n; ++i){
            x[i] = getsum(a[i]);
            add(a[i]);
        }

        memset(sum, 0, sizeof(sum));
        for(int i = n; i > 0; --i){
            y[i] = getsum(a[i]);
            add(a[i]);
        }

        long long ans = 0;
        for(int i = 2; i < n; ++i)
            ans += (long long)x[i] * (n-i-y[i]) + (long long)y[i] * (i-1-x[i]);
        printf("%lld\n", ans);
    }
    return 0;
}
时间: 2024-10-06 12:08:07

LA 4329 Ping pong (树状数组)的相关文章

UVALive 4329 Ping pong (树状数组)

白书上的例题.花了很多时间在找bug上,刚学树状数组,这道题add操作时要注意上限不是n. #include <bits/stdc++.h> using namespace std; #define ll long long const ll maxn = 1e5 + 10; ll C[maxn]; ll n; inline ll lowbit(ll x) { return x & (-x); } ll sum(ll x) { ll ret = 0; while(x > 0) {

HDU 2492 Ping pong (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Ping pong Problem Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To improve their skill rank

uva 1428 - Ping pong(树状数组)

题目链接:uva 1428 - Ping pong 题目大意:一条大街上住着n个乒乓球爱好者,经常组织比赛.每个人都有一个不同的能力值,每场比赛需要3个人,裁判要住在两个选手之间,并且能力值也要在选手之间,问说最多能举行多少场比赛. 解题思路:预处理出bi和ci分别表示说在1~i中能力值比第i个人小的人和i+1~n中能力值比第i个人小的.处理过程用树状数组维护即可. #include <cstdio> #include <cstring> #include <algorith

poj3928 Ping pong 树状数组

http://poj.org/problem?id=3928 Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2087   Accepted: 798 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player

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种比赛. 然后问题就

POJ 3928 Ping pong 树状数组模板题

开始用瓜神说的方法撸了一发线段树,早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组 树状数组: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #includ

POJ-3928 Ping pong(树状数组)

Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2985   Accepted: 1104 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To i

UVA1428 - Ping pong(树状数组)

题目链接 题目大意:有N个人,每个人都有一个技能值ai,现在要开展乒乓球比赛,要求要有两个选手和一个裁判,要求裁判需要在两名选手的中间而且技能值也是在两名选手的中间,问可以开展多少场比赛. 解题思路:对于第i个选手当裁判的话,设它前面位置的选手有ci个技能值比它低的,那么就有i - 1 - ci个比它高的,对于第i选手后面的位置,同样有di个技能值比它低的,那么就有N - i - di个比它高的.组合一下:ci?(N - i - di) + (i - 1 - ci) ? di.那么对于ci的值,

POJ3928Ping pong[树状数组 仿逆序对]

Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3109   Accepted: 1148 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To i

LA 4329 Ping pong

#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int Max=20010; const int inf=100000; int lm[Max],rm[Max],a[Max],c[Max*10]; int n; long long lowbit(long long x) { return x&-x; } int sum(long long x,