树形数组 java

2^k求法

int lowbit(int x)
{
     return x&(-x);    
}

lowbit()的返回值就是 2^k 次方的值。

基本树形数组的模板

import java.util.*;
    public class Main1{
        static int N=10010;
        static int n,x,ans;
        static int c[] = new int [N];
        static int a[] = new int [N];
        public static int sum(int n){
            int sum=0;
            while(n>0){
                sum+=c[n];
                n-=n&(-n);
            }
            return sum;
        }
        public static void add(int i ,int x,int n){
            while(i<=n){
                c[i]+=x;
                i+=i&(-i);
            }
        }
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            for(int i=1;i<=n;i++){
                a[i]= sc.nextInt();
                add(i,a[i],n);
            }
            ans=sum(n);
            System.out.println(ans);
        }
    }

例题:

hihocoder1524

树形数组求逆序对,用树形数组可以快速统计出ai>aj对的数量,时间复杂度可以很好的提升,先感慨一个大小为a的最大值的数组c,每当读入一个数时,我们可以用桶排序思想,将c[a[i]]加1,然后我们 统计c[1]~c[a[i]]

的和,ans-1(除去这个数本身)就是在这个数前面有多少个数比它小,我们只需要用i-ans就可以计算出前面有多少个数比他大,也就是逆序对的数量

    给定一个1-N的排列A1, A2, ... AN,如果Ai和Aj满足i < j且Ai > Aj,我们就称(Ai, Aj)是一个逆序对。  

    求A1, A2 ... AN中所有逆序对的数目。  
public class Main1{
    static int N = 10010;
    static int n,x,ans=0;
    
    static int c[]= new int [N];
    public static int sum(int n){
        int sum=0;
        while(n>0){
            sum+=c[n];
            n-=n&(-n);
        }
        return sum;
    }
    public static void add(int i,int x){
        while(i<=n){
            c[i]+=x;
            i+=i&(-i);
        }
    }
    public static void main(String[] args) {
            Scanner sc=new Scanner(System.in);
            n = sc.nextInt();
            for(int i=1;i<=n;i++){
                x=sc.nextInt();
                add(x,1);
                ans+=(i-sum(x));
                
            }
         System.out.println(ans);
    
        }
}
原文地址:https://www.cnblogs.com/ls-pankong/p/10504723.html