LA 4329 (树状数组) Ping pong

第一次写树状数组,感觉那个lowbit位运算用的相当厉害。

因为-x相当于把x的二进制位取反然后整体再加上1,所以最右边的一个1以及末尾的0,取反加一以后不变。

比如1000取反是0111加一得到1000,这样与运算以后不变

最右边的1左边部分取反,加一不会影响左半部分,所以与运算以后全部为0

对于这道题来说貌似不是很容易能联想到树状数组

注意题中说了每个人的技能值互不相同。

从左往右扫描每个a[i],另x[a[i]] = 1,然后统计x[1]...x[a[i]-1]的和就是第i个人左边技能值比他小的人数c[i],所以第i个人左边技能值比他大的人数就是i-1-c[i]

同样地,从右往左扫描a[i],也另x[a[i]] = 1,统计x[1]...x[a[i]-1]的和就是这个人右边技能值比他小的人数d[i],所以他右边技能值比他大的人数就是n-i-d[i]

在根据计数原理,求一下总的方案数就是sum{ c[i] * n-i-d[i] + d[i] * i-1-c[i] }

 1 #include <cstdio>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 inline int lowbit(int x) { return x & (-x); }
 7
 8 struct Fenwicktree
 9 {
10     int n;
11     vector<int> C;
12
13     void resize(int n) { this->n = n; C.resize(n); }
14     void clear() { fill(C.begin(), C.end(), 0); }
15
16     int sum(int x)
17     {
18         int ret = 0;
19         while(x)
20         {
21             ret += C[x];
22             x -= lowbit(x);
23         }
24         return ret;
25     }
26
27     void add(int x, int d)
28     {
29         while(x <= n)
30         {
31             C[x] += d;
32             x += lowbit(x);
33         }
34     }
35 }f;
36
37 const int maxn = 20000 + 10;
38 int a[maxn], c[maxn], d[maxn];
39
40 int main()
41 {
42     //freopen("in.txt", "r", stdin);
43
44     int T;
45     scanf("%d", &T);
46     while(T--)
47     {
48         int n, maxa = 0;
49         scanf("%d", &n);
50         for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); maxa = max(maxa, a[i]); }
51         f.resize(maxa); f.clear();
52         for(int i = 1; i <= n; i++)
53         {
54             f.add(a[i], 1);
55             c[i] = f.sum(a[i] - 1);
56         }
57         f.clear();
58         for(int i = n; i > 0; i--)
59         {
60             f.add(a[i], 1);
61             d[i] = f.sum(a[i] - 1);
62         }
63         long long ans = 0;
64         for(int i = 1; i <= n; i++) ans += (long long)c[i]*(n-i-d[i]) + (long long)d[i]*(i-1-c[i]);
65         printf("%lld\n", ans);
66     }
67
68     return 0;
69 }

代码君

时间: 2024-12-24 08:11:17

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

LA 4329(树状数组)

题目描述: N <tex2html_verbatim_mark>(3N20000) <tex2html_verbatim_mark>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, they often compete with

poj Ping pong LA 4329 (树状数组统计数目)

Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2302   Accepted: 879 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 im

Hdu 2492 树状数组 Ping pong

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define MAXN 100005 5 #define M 20005 6 typedef __int64 LL ; 7 using namespace std; 8 LL n,max_num ; 9 LL s[M],a[M],b[M],c[MAXN]; 10 LL lowbit(LL x){ 11 return x&(-x); 12

LA 2191 树状数组 稍修改

题意:给出n个数字,操作有修改(S)和输出区间和(M). #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <queue> #include <stack> #include <map> #include <

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

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的技能值的人数.类似逆着处理

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