• 16-求逆序数(树状数组)


    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

    eg:
    原序列: 4 5 1 3 2
    标准序列:1 2 3 4 5
    逆序数 :7

    可以用树状数组做:讲解:00:58 : 00   https://www.nowcoder.com/study/live/153/11/1

     

     对于标准的1到n的数字:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    int sum[50005];  //sum[x]表示的是区间为2^k个元素的和,k为x的二进制末尾0的个数,以为最后一个元素为a[x], 
    int n;			 //所以sum[x] = a[n - 2^k + 1] + ...+ a[x]; 看图理解	
    
    void update(int pos, int val){
    	while(pos <= n){  //一直更新到最后 
    		sum[pos] += val;
    		pos += (pos & (-pos));  //pos && (-pos)找到pos二进制末尾一个1 
    	}
    }
    
    int query(int pos){
    	int ans = 0;
    	while(pos > 0){   //一直加到0 
    		ans += sum[pos];
    		pos -= (pos & (-pos));
    	}
    	return ans;
    }
    int main(){
    	int ans = 0, x;
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++){
    		scanf("%d", &x);
    		update(x, 1);
    		for(int i = 1; i <= n; i++){
    			cout << sum[i] << " ";
    		}
    		cout << endl;
    		int temp = query(x);
    		ans += x - temp;
    		cout << temp << "tem" <<endl;
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    int sum[50005];  //sum[x]表示的是区间为2^k个元素的和,k为x的二进制末尾0的个数,以为最后一个元素为a[x], 
    int n;			 //所以sum[x] = a[n - 2^k + 1] + ...+ a[x]; 看图理解	
    struct node{
    	int pos, x;  //pos:记录输入的位置,x:值 
    }a[100005];
    int b[100005];
    
    bool cmp(node x, node y){
    	return x.x < y.x;
    }
    
    void update(int pos, int val){
    	while(pos <= n){  //一直更新到最后 
    		sum[pos] += val;
    		pos += (pos & (-pos));  //pos && (-pos)找到pos二进制末尾一个1 
    	}
    }
    
    int query(int pos){
    	int ans = 0;
    	while(pos > 0){   //一直加到0 
    		ans += sum[pos];
    		pos -= (pos & (-pos));
    	}
    	return ans;
    }
    int main(){
    	long long ans = 0, x;  //int错了 
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++){
    		scanf("%d", &a[i].x);
    		a[i].pos = i;
    	}
    	sort(a + 1, a + n + 1, cmp);
    	for(int i = 1; i <= n; i++){
    		b[a[i].pos] = i;
    	}
    	for(int i = 1; i <= n; i++){
    		x = b[i];
    		update(x, 1);
    		int temp = query(x);
    		ans += x - temp;
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

  • 相关阅读:
    论 IntStream 和 for 循环的速度
    单链线性表的基本操作--创建,插入,删除,查看,打印
    Android中的异步处理方式
    Kotlin 集合变换与序列
    Kotlin Lazy延迟初始化
    协程及Kotlin协程
    Java 注解
    Android 事件传递机制进阶
    Java 异常
    Java 多线程及线程间通信(Synchronized和Volatile关键字)
  • 原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/8469175.html
Copyright © 2020-2023  润新知