树状数组 _ 求逆序数
注: 本文只是记录 ,您将从上面学习不到任何知识,除了 代码
(废话)第一次接触到树状数组,感觉接触到了新世界,理解这个思想用了好长时间,终于弄明白了(似懂非懂)。
还有接触到了 离散化的思想, 逆序数 , 感觉数学这么有用
问题 A: 最少的交换
时间限制: 1 Sec 内存限制: 32 MB提交: 157 解决: 47
[提交][状态][讨论版][命题人:外部导入]
题目描述
现在给你一个由n个互不相同的整数组成的序列,现在要求你任意交换相邻的两个数字,使序列成为升序序列,请问最少的交换次数是多少?
输入
输入包含多组测试数据。每组输入第一行是一个正整数n(n<500000),表示序列的长度,当n=0时。
接下来的n行,每行一个整数a[i](0<=a[i]<=999999999),表示序列中第i个元素。
接下来的n行,每行一个整数a[i](0<=a[i]<=999999999),表示序列中第i个元素。
输出
对于每组输入,输出使得所给序列升序的最少交换次数。
样例输入
5
9
1
0
5
4
3
1
2
3
0
样例输出
6
0
import java.util.Arrays; import java.util.Scanner; /** * 树状数组 * @author Administrator * */ class Node implements Comparable<Node>{ public int index; public int value; public Node(int index,int value){ this.index = index; this.value = value; } @Override public int compareTo(Node n) { return this.value-n.value; } } public class TreeArrayDemo { private static int [] c ; private static int [] array = new int [500010]; private static int maxn; private static Node [] nodes ; public static int lowbit(int x){ return x&(-x); } public static int getSum(int x) { int sum = 0 ; for(int i = x;i>0;i-=lowbit(i)){ sum+=c[i]; } return sum; } public static void update(int x,int val) { for(int i = x;i<=maxn;i+=lowbit(i)){ c[i]+=val; } } public static void main(String[] args) { Scanner cin = new Scanner(System.in); while (cin.hasNext()) { maxn = cin.nextInt(); if(maxn == 0) { break; } nodes = new Node [500010]; c = new int [500010]; for(int i = 1;i<=maxn;i++){ int index = i; int val = cin.nextInt(); Node node = new Node(index, val); nodes[i] = node; } //给节点进行排序 Arrays.sort(nodes, 1,maxn+1); //对数据进行离散化 for(int i = 1;i<=maxn;i++){ array[nodes[i].index] = i; } for(int i = 1;i<=maxn;i++){ System.out.println(array[i]); } long answer = 0; for(int i = 1;i<=maxn;i++) { update(array[i], 1); int n = getSum(array[i]); answer+=i-n; } System.out.println(answer); } } }