LA 4329 乒乓比赛

https://vjudge.net/problem/UVALive-4329

题意:

一条大街上住着n个兵乓球爱好者,经常组织比赛切磋技术。每个人都有一个不同的技能值ai。每场比赛需要3个人:两名选手,一名裁判。他们有一个奇怪的规定,即裁判必须住在两名选手的中间,并且技能值也在两名选手之间。问一共能组织多少种比赛。

 

思路:

想了好久才明白二叉索引树在这里的运用。

首先,就像训练指南上说的,考虑第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-ci-1)di种比赛。这样,问题就转化为ci和di。

接下来就是二叉索引树的应用,我们从左往右扫描a[i],计算c[]值。

 1 #include<iostream> 
 2 #include<algorithm>
 3 #include<string>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 const int maxn = 100000 + 5;
 8 int n;
 9 int a[maxn],c[maxn],s1[maxn],s2[maxn];
10 
11 
12 int lowbit(int x)
13 {
14     return x&-x;
15 }
16 
17 int sum(int x)
18 {
19     int ret = 0;
20     while (x > 0)
21     {
22         ret += c[x];
23         x -= lowbit(x);
24     }
25     return ret;
26 }
27 
28 void add(int x, int d)
29 {
30     while (x <= maxn)
31     {
32         c[x] += d;
33         x += lowbit(x);
34     }
35 }
36 
37 int main()
38 {
39     ios::sync_with_stdio(false);
40     //freopen("D:\\txt.txt", "r", stdin);
41     int T;
42     cin >> T;
43     while (T--)
44     {
45         cin >> n;
46         for (int i = 1; i <= n; i++)
47             cin >> a[i];
48         memset(c, 0, sizeof(c));
49         for (int i = 1; i <= n; i++)
50         {
51             add(a[i], 1);
52             s1[i] = sum(a[i] - 1);
53         }
54         memset(c, 0, sizeof(c));
55         for (int i = n; i >= 1; i--)
56         {
57             add(a[i], 1);
58             s2[i] = sum(a[i] - 1);
59         }
60         long long ans = 0;
61         for (int i = 2; i <= n-1; i++)
62         {
63             ans += s1[i] * (n - i - s2[i]) + (i - s1[i] - 1)*s2[i];
64         }
65         cout << ans << endl;
66     }
67 }

 

转载于:https://www.cnblogs.com/zyb993963526/p/6527149.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值