(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 #include<math.h>
 8 using namespace std;
 9 typedef long long LL;
10 int bitl[200005];
11 int bitr[200005];
12 int lowbit(int x);
13 void addl(int x);
14 void addr(int x);
15 int  askl(int x);
16 int askr(int x);
17 int ans[100005];
18 int bns[100005];
19 int aksl[200005];
20 int aksr[200005];
21 int main(void)
22 {
23         int T;
24         scanf("%d",&T);
25         while(T--)
26         {
27                 int n;
28                 scanf("%d",&n);
29                 memset(bitl,0,sizeof(bitl));
30                 memset(bitr,0,sizeof(bitr));
31                 int i,j;
32                 for(i = 1; i <= n; i++)
33                 {
34                         scanf("%d",&ans[i]);
35                 }
36                 int cn = 1;
37                 for(i = n; i >= 1; i--)
38                 {
39                         bns[cn++] = ans[i];
40                 }
41                 for(i = 1; i <= n; i++)
42                 {
43                     aksl[i] = askl(ans[i]-1);
44                     addl(ans[i]);
45                     aksr[i] = askr(bns[i]-1);
46                     addr(bns[i]);
47                 }
48                 LL sum = 0;
49                 for(i = 2;i <= n-1;i++)
50                 {
51                     sum = sum + (LL)aksl[i]*(LL)(n-i-aksr[n-i+1])+(LL)(i - 1 - aksl[i])*(LL)aksr[n-i+1];
52                 }
53                 printf("%lld\n",sum);
54         }
55         return 0;
56 }
57 int lowbit(int x)
58 {
59         return x&(-x);
60 }
61 void addl(int x)
62 {
63         while(x <= 100000)
64         {
65                 bitl[x]++;
66                 x += lowbit(x);
67         }
68 }
69 void addr(int x)
70 {
71         while(x <= 100000)
72         {
73                 bitr[x]++;
74                 x += lowbit(x);
75         }
76 }
77 int  askl(int x)
78 {
79         int sum = 0;
80         while(x > 0)
81         {
82                 sum += bitl[x];
83                 x -= lowbit(x);
84         }
85         return sum;
86 }
87 int askr(int x)
88 {
89         int sum = 0;
90         while(x > 0)
91         {
92                 sum += bitr[x];
93                 x -= lowbit(x);
94         }
95         return sum;
96 }
时间: 2024-10-11 12:25:49

(4329)Ping pong的相关文章

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

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,

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

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

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

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

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