标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2691 | Accepted: 996 |
Description
Input
Output
Sample Input
1 3 1 2 3
Sample Output
1
题意:n个乒乓球爱好者,进行比赛。每个人都有一个技能值 ai。每场比赛需要 3 个人:两名选手,一名裁判。他们有一个奇怪的规定,即裁判必须住在两名选手之间,并且技能值也介于两名选手之间,问一共能组织多少种比赛
分析: 枚举裁判k,看看k前面有多小比他小,后面比他大 或者 前面有多少比他大后面有多少比他小,乘加
树状数组解决统计k后面有多少比他大的数
解决方案:每个数用一个结构体{id和value}表示,按照value从小到大排序,然后使让后面大的id + 1,即可
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int Max = 20000 + 10; typedef long long LL; struct Node { int id,value; }; Node data[Max]; int n,c[Max]; int cmp(Node x, Node y) { return x.value < y.value; } int lowbit(int k) { return k & (-k); } LL sum(int k) { LL ans = 0; while(k > 0) { ans += c[k]; k -= lowbit(k); } return ans; } void modify(int k, int y) { while(k <= n) { c[k] += y; k += lowbit(k); } } int main() { int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &data[i].value); data[i].id = i; } sort(data + 1, data + 1 + n, cmp); memset(c, 0, sizeof(c)); LL l, r, ans = 0; for(int i = 1; i <= n; i++) { l = sum(data[i].id); //比 data[i].value小的个数 r = sum(n) - l; ans += (l * (n - data[i].id - r)) + (r * (data[i].id - 1 - l)); modify(data[i].id, 1); //所以比data[i].id大的都跟新 } printf("%I64d\n", ans); } return 0; }
POJ3928 Pingpong(统计比 K 小的个数 + 树状数组)
标签:
原文地址:http://www.cnblogs.com/zhaopAC/p/5244241.html