树状数组复习+模板整理(8.1号更新)

资料:

求逆序对:https://blog.csdn.net/ssimple_y/article/details/53744096

离散化:https://blog.csdn.net/xiangaccepted/article/details/73276826

一、离散化+求逆序对数

//a[i] = 5, 将5插进数组,然后求5和5前面出现的数x,本来5是第i个出现,前面出现了x-1个比5小的,所以i-1-(x-1)就是前面出现的比5大的数,就是逆序对数。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 5e5+10;
const double eps = 1e-8;
const double pi = acos(-1.0);
int a[maxn],t[maxn],c[maxn];
int n;


int getsum(int x)
{
    int sum = 0;
    while(x>0)
    {
        sum += c[x];
        x -= x&(-x);
    }
    return sum;
}

void add(int x,int k)
{
    while(x<=n)
    {
        c[x] += k;
        x += x&(-x);
    }
}

int main()
{
    while(scanf("%d",&n)!=EOF&&n)
    {

        for(int i=1;i<=n;i++)
        {
            c[i] = 0;
            scanf("%d",&a[i]);
            t[i] = a[i];
        }

        sort(t+1,t+n+1);
        int m = unique(t+1,t+1+n)-t-1;
        for(int i=1;i<=n;i++)
        {
            a[i] = lower_bound(t+1,t+1+m,a[i])-t;
        }

        ll ans = 0;
        for(int i=1;i<=n;i++)
        {
            add(a[i],1);
            ans += (ll)i-getsum(a[i]);
                        //i第i个位置,getsum(a[i])=a[i]前出现的数
                        //a[i] = 5, 将5插进数组,然后求5和5前面出现的数x,本来5是第i个出现,前面出现了x-1个比5小的,所以i-1-(x-1)就是前面出现的比5大的数,就是逆序对数。
        }
        printf("%lld
",ans);
    }
}    
View Code

正反求两次逆序对(对于第i项,求前面比i小的和前面比i大的,求后面比i小的和后面比i大的)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define lowbit(x) x&(-x)

#define readint(x) scanf("%d",&x);
#define readll(x) scanf("%lld",&x);
#define readdb(x) scanf("%lf",&x);
#define reads(x) scanf("%s",x);
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,r,l) for(int i=r;i>=l;--i)

using namespace std;
typedef long long ll;
const int maxn = 3e5+10;
const double eps = 1e-8;
const double pi = acos(-1.0);
ll a[maxn],c[maxn];
int n;


ll getsum(ll x)
{
    ll sum = 0;
    while(x>0)
    {
        sum += c[x];
        x -= lowbit(x);
    }
    return sum;
}

void add(ll x,ll k)
{
    while(x<maxn)
    {
        c[x] += k;
        x += lowbit(x);
    }
}

ll nxt_big[maxn],nxt_small[maxn],pre_big[maxn],pre_small[maxn];

int main()
{
    int T;
    readint(T);
    while(T--)
    {
        int n;
        readint(n);
        int x,y;
        memset(pre_small,0,sizeof(pre_small));
        memset(pre_big,0,sizeof(pre_big));
        memset(nxt_small,0,sizeof(nxt_small));
        memset(nxt_big,0,sizeof(nxt_big));
        memset(c,0,sizeof(c));
        memset(a,0,sizeof(a));
        rep(i,1,n)
        {
            readll(a[i]);
            pre_small[i] = getsum(a[i]);
            add(a[i],1);
            pre_big[i] = i-pre_small[i]-1;
        }
        memset(c,0,sizeof(c));
        per(i,n,1)
        {
            nxt_small[i] = getsum(a[i]);
            add(a[i],1);
            nxt_big[i] = n-i-nxt_small[i];
        }
        ll ans = 0;
        rep(i,1,n)
        {
            ans += pre_small[i]*nxt_big[i];
            ans += pre_big[i]*nxt_small[i];
        }
        printf("%lld
",ans);
    }
}
View Code
原文地址:https://www.cnblogs.com/WWkkk/p/9400074.html