Ping pong

OJ题号:LA4329

思路:

树状数组。

参考刘汝佳《训练指南》P197。

  考虑第$i$个人当裁判的情形。假设$a_1$到$a_{i-1}$中有$c_i$个比$a_i$小,那么就有$(i-1)-c_i$个比$a_i$大;同理,假设$a_{i+1}$到$a_n$中有$d_i$个比$a_i$小,那么就有$(n-i)-d_i$个比$a_i$大。根据乘法原理和加法原理,$i$当裁判有$c_i(n-i-d_i)+(i-c_i-1)d_i$种比赛。这样,问题就转化为求$c_i$和$d_i$。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define maxn 20001
 4 #define maxa 100001
 5 int t,n,a[maxn],c[maxn],d[maxn];
 6 struct BIT {
 7     int val[maxa];
 8     void reset() {
 9         memset(val,0,sizeof val);
10     }
11     int lowbit(const int x) {
12         return x&-x;
13     }
14     void modify(int p) {
15         while(p<=maxa) {
16             val[p]++;
17             p+=lowbit(p);
18         }
19     }
20     int query(int p) {
21         int ans=0;
22         while(p) {
23             ans+=val[p];
24             p-=lowbit(p);
25         }
26         return ans;
27     }
28 };
29 BIT tree;
30 int main() {
31     scanf("%d",&t);
32     while(t--) {
33         scanf("%d",&n);
34         tree.reset();
35         for(int i=1;i<=n;i++) {
36             scanf("%d",&a[i]);
37             tree.modify(a[i]);
38             c[i]=tree.query(a[i]-1);
39         }
40         tree.reset();
41         for(int i=n;i;i--) {
42             tree.modify(a[i]);
43             d[i]=tree.query(a[i]-1);
44         }
45         long long ans=0;
46         for(int i=1;i<=n;i++) ans+=(long long)c[i]*(n-i-d[i])+(long long)d[i]*(i-1-c[i]);
47         printf("%lld\n",ans);
48     }
49     return 0;
50 }

 

posted @ 2017-05-16 20:36  skylee03  阅读(168)  评论(0编辑  收藏  举报