树状数组之求逆对数

Ultra-QuickSort

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 
9 1 0 5 4 ,
Ultra-QuickSort produces the output 
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

Input

The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

Output

For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

Sample Input

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0

题目是求每个数前面比它大的数量的总和,就是逆对数了。只要是离散化就可以做了。i-query(index[i]):当前是对i个数,query(index[i])是它前面比它小的数,减去它就是前面比它大的数量了。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #define lowbit(x) x&(-x)
 6 #define ll long long
 7 using namespace std;
 8 const int MAX = 5e5+5;
 9 int n, tree[MAX],index[MAX];
10 struct Nod{
11     int num,id;
12 }nod[MAX];
13 bool cmp(Nod a, Nod b){
14     return a.num < b.num;
15 }
16 void add(int x, int y){
17     while(x < MAX){
18         tree[x] += y;
19         x += lowbit(x);
20     }
21 }
22
23 int query(int x){
24     int sum = 0;
25     while(x > 0){
26         sum += tree[x];
27         x -= lowbit(x);
28     }
29     return sum;
30 }
31 int main(){
32     while(scanf("%d",&n)&&n){
33         for(int i = 1; i <= n; i ++){
34             scanf("%d",&nod[i].num);
35             nod[i].id = i;
36         }
37         sort(nod+1,nod+1+n,cmp);
38         for(int i = 1; i <= n; i ++)index[nod[i].id] = i;
39         memset(tree,0,sizeof(tree));
40         ll ans = 0;
41         for(int i = 1; i <= n; i ++){
42             add(index[i],1);
43             //printf("%d+++++%d\n",index[i],query(index[i]));
44             ans += i-query(index[i]);
45         }
46         printf("%lld\n",ans);
47     }
48 }

Enemy is weak

The Romans have attacked again. This time they are much more than the Persians but Shapur is ready to defeat them. He says: "A lion is never afraid of a hundred sheep".

Nevertheless Shapur has to find weaknesses in the Roman army to defeat them. So he gives the army a weakness number.

In Shapur‘s opinion the weakness of an army is equal to the number of tripletsi,?j,?k such that i?<?j?<?k and ai?>?aj?>?ak where ax is the power of man standing at position x. The Roman army has one special trait — powers of all the people in it are distinct.

Help Shapur find out how weak the Romans are.

Input

The first line of input contains a single number n (3?≤?n?≤?106) — the number of men in Roman army. Next line contains n different positive integers ai (1?≤?i?≤?n,?1?≤?ai?≤?109) — powers of men in the Roman army.

Output

A single integer number, the weakness of the Roman army.

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cout (also you may use %I64d).

Example

Input

33 2 1

Output

1

Input

32 3 1

Output

0

Input

410 8 3 1

Output

4

Input

41 5 4 3

Output

1

这个就是求三个递增的数量,也可以看成第i个数,求前面比它大的数量和后面比它小的数量。下面k是前面比它大的数量,求后面比它小的数量:由于k是第i个数前面比第i个数大的数量,所以后面比第i个数小的数量                 为(n-index[i])-(i-1-k)就是n-i-index[i]+k+1,(n-index[i])是比第i个数小的                 总数,把它减去前面比第i个数小的数量就是后面的数量了,前面比第i个数小的                 数量为(i-1-k),所以(n-index[i])-(i-1-k)就推来了
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #define lowbit(x) x&(-x)
 6 #define ll long long
 7 using namespace std;
 8 const int MAX = 1e6+10;
 9 int n,tree[MAX],index[MAX];
10 int nex[MAX],pre[MAX];
11 struct Nod{
12     int val,id;
13 }nod[MAX];
14 bool cmp(Nod a, Nod b){
15     return a.val > b.val;
16 }
17 void add(int x){
18     while(x < MAX){
19         tree[x] ++;
20         x += lowbit(x);
21     }
22 }
23 int query(int x){
24     int sum = 0;
25     while(x > 0){
26         sum += tree[x];
27         x -= lowbit(x);
28     }
29     return sum;
30 }
31 int main(){
32     scanf("%d",&n);
33     for(int i = 1; i <= n; i ++)scanf("%d",&nod[i].val),nod[i].id=i;
34     sort(nod+1,nod+1+n,cmp);
35     for(int i = 1; i <= n; i ++)index[nod[i].id] = i;
36     ll ans = 0,k;
37
38     for(int i = 1; i <= n; i ++){
39         k = query(index[i]);
40         ans += k*(n-i-index[i]+k+1);
41         add(index[i]);
42     }
43     cout << ans << endl;
44     return 0;
45 }
时间: 2024-10-10 00:59:11

树状数组之求逆对数的相关文章

HDU 1394 树状数组+离散化求逆序数

对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们通过树状数组可以明显提高时间效率. 我们可以按照排列的顺序依次将数字放入树状数组中,并依次更新预与之相关联的树状数组元素.那么在将其更新完毕后,我们知道每个数对应的树状数组元素的左边的数肯定比它小,我们在以序列顺序依次更新树状数组时,如果有值在它前面出现,那么它对应的树状数组元素(在这个题目里存放的

POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 9 1 0 5

Inversion (hdu 4911 树状数组 || 归并排序 求逆序对)

Inversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 2003    Accepted Submission(s): 787 Problem Description bobo has a sequence a1,a2,-,an. He is allowed to swap two adjacent numbers fo

poj 2299 Ultra-QuickSort(线段树/树状数组/归并 求逆序对)

Problem: 2299 User: shu_dayang Memory: 7380K Time: 500MS Language: C++ Result: Accepted Source Code//树状数组 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> typedef long long LL; #define MAXN 500005 #define M

POJ2299 Ultra-QuickSort【树状数组】【逆序数】

题目链接: http://poj.org/problem?id=2299 题目大意: 给你一个包含N个整数的序列,只能通过交换相邻的数字,最终变为升序顺序,问:最少需要多少次交换. 思路: 其实就是问冒泡排序的交换次数.其实就是求原序列的逆序数.用归并排序.线段树.树状数组都可以做. 但是如果用线段树和树状数组来做的话,因为元素个数是500000,但是元素值范围却是999999999,需 要先离散化.这里用间接排序的方法.用一个数组Arr[]存放原序列的值,另一个数组Id[]存放原序列编号 (1

hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场

题意: 输入一行数字,查询第i个数到第j个数之间的最大值.可以修改其中的某个数的值. 输入: 包含多组输入数据. 每组输入首行两个整数n,m.表示共有n个数,m次操作. 接下来一行包含n个整数. 接下来m行,每行包含一个字母s,两个整数a,b. 当s为’Q’,表示查询第a个数到第b个数之间的最大值. 当s为’U’,表示将第a个数更改为b. 输出: 每次查询输出一个结果,每次输出占一行. 题解: 点修改区间求最值,可以用树状数组模板. 具体见代码—— 1 #include <cstdio> 2

hdu4417 树状数组(求指定区间比指定数小的数的个数)

http://acm.hdu.edu.cn/showproblem.php?pid=4417 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover.

【BZOJ3295】【块状链表+树状数组】动态逆序对

Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的个数. Sample Input 5 4 1 5 3

ACM--归并排序&amp;&amp;树状数组--nyoj 117--求逆序数

南阳oj题目地址:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=117 求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组