CF Gym 100463A (树状数组求逆序数)

题意:给你一个序列,和标准序列连线,求交点数。

题解:就是求逆序对个数,用树状数组优化就行了。具体过程就是按照顺序往树状数组了插点(根据点的大小),因为第i大的点应该排在第i位,插进去的时候他前面本该是有i-1个点的,如果少了,那么一定就和这个元素构成了逆序对。

做八数码的时候,求逆序数搜过怎么求,但是练习时忘了。。。于是当场想怎么实现,结果搞了1个小时才搞出来,还被WA了个LongLong,基础还不够扎实

#include<cstdio>

#include<cmath>

#include<vector>

#include<map>

#include<set>

#include<algorithm>

#include<cstring>



using namespace std;



//#define local

typedef long long  ll;

const int maxn = 1000000+100;

#define lowbit(x) ((x)&-(x))

ll C[maxn];

ll n,a,b;

void add(ll x,ll d)

{

    while(x <= n) {

        C[x]+=d; x+=lowbit(x);

    }

}



ll sum(ll x)

{

    ll ret = 0;

    while(x > 0){

        ret += C[x]; x-=lowbit(x);

    }

    return ret;

}



ll Count()

{

    ll res = 0;

    ll ele = b;

    for(int i = 0; i < n; i++){

        ll pre = sum(ele+1);

        res += ele - pre;

        add(ele+1,1);

        ele = (ele+a)%n;

    }

    return res;

}



int main()

{

#ifdef local

    freopen("in.txt","r",stdin);

    //freopen("out.txt","w",stdout);

#endif // local

    int cas = 0;

    while(~scanf("%I64d%I64d%I64d",&n,&a,&b)&&n){

        memset(C,0,sizeof(C));

        printf("Case %d: %I64d\n",++cas,Count());

    }



    return 0;

}

 

你可能感兴趣的:(树状数组)