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,int *c)
{
    int ret=0;
    while(x>0)
    {
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}
void add(long long x,int d,int *c)
{
    while(x<=inf)      //从x到inf的数组都拥有一个小于等于x的数:x
    {
        c[x]+=d;
        x+=lowbit(x);
    }
}
int main()
{
    int T;
    for(scanf("%d",&T);T;T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(c,0,sizeof(c));
        add(a[1],1,c);
        for(int i=2;i<=n;i++)
        {
            lm[i]=sum(a[i],c);
            add(a[i],1,c);
        }
        memset(c,0,sizeof(c));
        add(a[n],1,c);
        for(int i=n-1;i>=1;i--)
        {
            rm[i]=sum(a[i],c);
            add(a[i],1,c);
        }
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
  //          cout<<i<<" lm: "<<lm[i]<<" rm: "<<rm[i]<<endl;
            ans+=lm[i]*(n-i-rm[i])+(i-1-lm[i])*rm[i];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

题意:n个人,每个人都有一个能力值,每次举办比赛都要三个人,举办条件:

如果 i,j,k进行比赛时,如果k是裁判,必须要i<j<k(下标)而且ai<aj<ak(能力值)

思路:只要枚举每个人当裁判是他左边小于他的数个数lm和他右边小于他的数的个数rm

那么答案就是(左边总人数-lm)*(rm)+(lm)*(右边总人数-rm)

如果对每个lm和rm进行枚举的话那么时间会是n^2

可以对树状数组的add操作加以改变,将从ci数组定以为此时ai出现之前的小于ai的数的个数

动态加一,然后求1到ai的sum值

时间: 2024-12-12 22:55:31

LA 4329 Ping pong的相关文章

BIT LA 4329 Ping pong

题目传送门 题意:训练指南P197 分析:枚举裁判的位置,用树状数组来得知前面比它小的和大的以及后面比它小的和大的,然后O (n)累加小 * 大 + 大 * 小 就可以了 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 5; const int M = 2e4 + 5; struct BIT { int c[N], sz; void init(int n) { mem

ACM-ICPC LA 4329 Ping pong(树状数组)

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2330 参考资料:<算法入门经典训练指南>刘汝佳 P197 这本书上面写的题目大意.解题思路都写出来了. 在这我贴上自己的 AC代码: 1 #include<stdio.h> 2 #include<string.h> 3 4 #define

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) +

UVAlive - 4329 —— Ping pong 【树状数组】

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13895 #include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; const int MAXA = 100000 + 5; int n; int c[MAXA]; int sum(int i) { int

(4329)Ping pong

思路:树状数组. 考虑第i个人当裁判,那么只要计算出在他之前比他小的乘在他之后比他大的与在他之前比他大的乘在他之后比他小的,那么用两个树状数组维护一下就行了.复杂的(n*log(n)) 1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<queue> 6 #include<stack> 7 #inc

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) {

UVALive 4329 Ping pong(树状数组)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13895 题意:一条街上住有n个乒乓选手,每个人都有一个技能值,现在每场比赛需要3个人,两个选手,一个裁判:裁判须住在他们之间,且其技能值必须在两选手之间,求一共能组织多少种比赛. 注意到技能值的范围(1 ≤ ai ≤ 100000),所以我们可以树状数组(O(nlogn))处理得到一个ll数组,ll[x]表示住在x左边的并且技能值小于x的技能值的人数.类似逆着处理

UVALIVE 4329 Ping pong

大白上的题目 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string&g

UVALive 4329 Ping pong (BIT)

枚举中间的人,只要知道在这个人前面的技能值比他小的人数和后面技能值比他小的人数就能计算方案数了,技能值大的可有小的推出. 因此可以利用树状数组,从左到右往树上插点,每个点询问sum(a[i]-1)就是前面的技能值比它小的人数,然后再从右边往左重复一遍就可以算出答案. #include<bits/stdc++.h> using namespace std; const int maxa = 1e5+2; #define lowbit(x) (x&-x) int C[maxa]; int