HDU 5792:World is Exploding(树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=5792

World is Exploding

Problem Description

Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.

Input

The input consists of multiple test cases. 
Each test case begin with an integer n in a single line.

The next line contains n integers A1,A2?An.
1≤n≤50000
0≤Ai≤1e9

Output

For each test case,output a line contains an integer.

 

Sample Input

4

2 4 1 3

4

1 2 3 4

Sample Output

1

0

Insipired by http://blog.csdn.net/libin66/article/details/52098019

题意:比较简单直接看。

思路:分别求出在 i 的时候前面有多少比它小的(即像Aa,Ab这样升序的有多少对),用up记录,后面有多少比它小的(像Ac,Ad这样降序的有多少对),用down记录,然后ans = up * down,因为有很多重复。用树状数组维护四个数组,ls —— 在[1,i-1]有多少比a[i]小的,rs —— 在[i+1,n]有多少比a[i]小的,lb —— 在[1,i-1]有多少比a[i]大的,rb —— 在[i+1,n]有多少比a[i]大的。由容斥原理要减去 (  ls * lb + rs * rb + ls * rs + lb * rb )。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 #define N 50005
 6 #define MOD 1000000007
 7 typedef long long LL;
 8 LL ls[N], lb[N], rs[N], rb[N], bit[N];
 9 int a[N], num[N], n, m;
10
11 /*
12 ls和lb是[1,i-1]中比a[i]小的数的数量,比a[i]大的数的数量
13 rs和rb是[i+1, n]中比a[i]小的数的数量,比a[i]大的数的数量
14 这些都可以通过树状数组实现
15 由于答案会多算进去a=c || a=d || b=c || b=d的情况,那么枚举这四种情况减去就可以了(a=c那么必定b!=d,同理其他
16 a=c:ans-=rs[i]*rb[i]
17 a=d:ans-=lb[i]*rb[i]
18 b=c:ans-=ls[i]*rs[i]
19 b=d:ans-=lb[i]*ls[i]
20 */
21
22 void init()
23 {
24     memset(ls, 0, sizeof(ls));
25     memset(lb, 0, sizeof(lb));
26     memset(rs, 0, sizeof(rs));
27     memset(rb, 0, sizeof(rb));
28     memset(sum, 0, sizeof(sum));
29 }
30
31 int lowbit(int x)
32 {
33     return x & (-x);
34 }
35
36 void update(int pos)
37 {
38     while(pos <= m) {
39         bit[pos]++;
40         pos += lowbit(pos);
41     }
42 }
43
44 LL query(int pos)
45 {
46     LL ans = 0;
47     while(pos > 0) {
48         ans += bit[pos];
49         pos -= lowbit(pos);
50     }
51     return ans;
52 }
53
54 int main()
55 {
56     while(~scanf("%d", &n)) {
57         init();
58         for(int i = 1; i <= n; i++) {
59             scanf("%d", &a[i]);
60             num[i] = a[i];
61         }
62         sort(a+1, a+1+n);
63         m = unique(a+1, a+1+n) - (a+1);
64         for(int i = 1; i <= n; i++)
65             num[i] = lower_bound(a+1, a+1+m, num[i]) - a;
66
67         LL up = 0, down = 0;
68         memset(bit, 0, sizeof(bit));
69         for(int i = 1; i <= n; i++) {
70             ls[i] = query(num[i] - 1);
71             lb[i] = query(m) - query(num[i]);
72             up += ls[i];
73             update(num[i]);
74         }
75
76         memset(bit, 0, sizeof(bit));
77         for(int i = n; i >= 1; i--) {
78             rs[i] = query(num[i] - 1);
79             rb[i] = query(m) - query(num[i]);
80             down += rs[i];
81             update(num[i]);
82         }
83
84         LL ans = 0;
85
86         for(int i = 1; i <= n; i++) {
87             ans -= ls[i] * lb[i];
88             ans -= rs[i] * ls[i];
89             ans -= rb[i] * lb[i];
90             ans -= rb[i] * rs[i];
91         }
92
93         printf("%I64d\n", up * down + ans);
94     }
95     return 0;
96 }
时间: 2024-10-11 15:17:41

HDU 5792:World is Exploding(树状数组)的相关文章

hdu 3015 Disharmony Trees (离散化+树状数组)

Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 663    Accepted Submission(s): 307 Problem Description One day Sophia finds a very big square. There are n trees in the square. T

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

HDU 3584 Cube (三维 树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3584 Cube Problem Description Given an N*N*N cube A, whose elements are either 0 or 1. A[i, j, k] means the number in the i-th row , j-th column and k-th layer. Initially we have A[i, j, k] = 0 (1 <= i, 

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的

hdu 5592 ZYB&#39;s Game 树状数组

ZYB's Game Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5592 Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to restore the premutation

HDU 1394 Minimum Inversion Number 树状数组&amp;&amp;线段树

题目给了你一串序列,然后每次 把最后一个数提到最前面来,直到原来的第一个数到了最后一个,每次操作都会产生一个新的序列,这个序列具有一个逆序数的值,问最小的你逆序数的值为多少 逆序数么 最好想到的是树状数组,敲了一把很快,注意把握把最后一个数提上来对逆序数的影响即可, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #i

HDU 6447 - YJJ&#39;s Salesman - [树状数组优化DP][2018CCPC网络选拔赛第10题]

Problem DescriptionYJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the way to destination.One day, he is going to travel from city A to southeastern city B. Let us assume th

HDU 1394 Minimum Inversion Number (树状数组求逆序数)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13942    Accepted Submission(s): 8514 Problem Description The inversion number of a given number sequence a1, a2, ..., a

hdu 5517 Triple(二维树状数组)

题目链接:hdu 5517 Triple 题意: 有n个两元组A,有m个三元组B,然后set C有一个计算方式. 现在让你找set TOP的size. 题解: 理解题意后,显然对于每个b的分组,只有最大的a才有贡献, 然后就可以发现set B中每个元素按照e分组后,只会对应一个a,所以最多有1e5个三元组可能有贡献. 然后将这个三元组排一下序,用二维树状数组搞搞就行了. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i&l

hdu 4456 Crowd(二维树状数组)

题目链接:hdu 4456 Crowd 题目大意:给定N,然后M次操作 1 x y z:在x,y的位置加z 2 x y z:询问与x,y曼哈顿距离小于z的点值和. 解题思路:将矩阵旋转45度,然后询问就等于是询问一个矩形,可以用容斥定理搞,维护用二维树状数组,但是空间开 不下,直接用离散化,将有用到的点处理出来. #include <cstdio> #include <cstring> #include <algorithm> using namespace std;