NYOJ-117 求逆序数(离散化+树状数组)/(归并)

来源:互联网 发布:精准扶贫数据平台登录 编辑:程序博客网 时间:2024/05/23 11:19

求逆序数

时间限制:2000 ms  |  内存限制:65535 KB
难度:5
描述

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

现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。

比如 1 3 2 的逆序数就是1。

输入
第一行输入一个整数T表示测试数据的组数(1<=T<=5)
每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000)
随后的一行共有N个整数Ai(0<=Ai<1000000000),表示数列中的所有元素。

数据保证在多组测试数据中,多于10万个数的测试数据最多只有一组。
输出
输出该数列的逆序数
样例输入
221 131 3 2
样例输出
01
来源
[张云聪]原创


1.

因为cmp函数wa了好久,给的1 1 不能发现问题,多测数据才能发现问题

 #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const int N = 1000005;struct node{    int pos;    ll val;}nod[N];int C[N],r[N];int n;bool cmp(node a,node b){    if(a.val == b.val)        return a.pos < b.pos;    return a.val < b.val;}int lowbit(int t){    return t&(-t);}void add(int t){    while(t <= N)    {        C[t] += 1;        t += lowbit(t);    }}//求得前面小于当前的数的个数ll getnum(int t){    ll ans = 0;    while(t > 0)    {        ans += C[t];        t -= lowbit(t);    }    return ans;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        memset(C,0,sizeof(C));        for(int i = 1;i <= n;i++)        {            scanf("%lld",&nod[i].val);            nod[i].pos = i;        }        sort(nod+1, nod+1+n,cmp);//先sort        for(int i = 1;i <= n;i++)//离散化处理            r[nod[i].pos] = i;        ll ans = 0,k;        for(int i = 1;i <= n;i++)        {            add(r[i]);            k = i - getnum(r[i]);            ans += k;        }        printf("%lld\n",ans);    }    return 0;}        


2.归并,然而并没有彻底理解,就不贴代码了,网上一片一片的。

以后来补理解

0 0