• 树状数组求逆序对


    Preface

    求逆序对的方法有两种一个是归并排序,一个是树状数组。在这里只讲怎么用树状数组求逆序对

    什么是逆序对?

    逆序对就是序列中(a_i>a_j)(i < j)的有序对。

    我们可以先按照权值从大到小排序,现在要求的就是对于一个点有多少在他前面的点下标小于这个点。

    那么这个东西怎么弄呢?我们可以用树状数组维护。从头到尾扫一遍,对于每个点,答案就是在这个点下标之前的下标有几个已经被访问过,在将这个点在树状数组中+1,表示为被访问过

     for(int i=1;i<=n;i++)
            ans+=sum(a[i].id),add(a[i].id,1);
    

    但是要注意判重复的元素

    code

    #include<bits/stdc++.h>
    #define int long long
    #define rg register
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    int read(){
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    struct node {
        int x,id;
    }a[500001];
    int c[500001<<2],n,ans,bj[500001];
    bool cmp(const node & a , const node & b ){
        if(a.x==b.x)
            return a.id>b.id;
        return a.x>b.x;
    }
    int lowbit(int x){
        return x&(-x);
    }
    int sum(int x){
        int ans=0;
        while(x>0){
            ans+=c[x];
            x-=lowbit(x);
        }
        return ans;
    }
    void add(int x,int v){
        while(x<=n){
            c[x]+=v;
            x+=lowbit(x);
        }
    }
    main(){
        n=read();
        for(int i=1;i<=n;i++)
            a[i].id=i,a[i].x=read();
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n;i++)
            ans+=sum(a[i].id),add(a[i].id,1);
        printf("%lld",ans);
        return 0;
    }
    
    
  • 相关阅读:
    SharedPreferences
    Handler
    Gallery 和ImageSwitcher
    poj 1077 Eight (BFS)
    HDU 1208 Pascal's Travels( 记忆化搜索)
    HDU 1619 Unidirectional TSP (dp,dfs)
    HDU 3683 Gomoku (枚举+BFS)
    HDU 3647 Tetris (暴力DFS)
    poj 1020 Anniversary Cake (DFS)
    poj 1375 Intervals(解析几何 过圆外一点求与圆的切线)
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10138151.html
Copyright © 2020-2023  润新知