nyoj 117 求逆序数【线段树 树状数组 归并排序】

来源:互联网 发布:盗梦空间limbo 知乎 编辑:程序博客网 时间:2024/05/29 06:43

求逆序数

时间限制: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
线段树lazy:1536ms
 #include <cstdio>#include <cstring>#include <algorithm>#define MAX 1000000+10#define LL long longusing namespace std;int sum[MAX<<2];struct record{    int val, pos;}num[MAX];bool cmp(record a,record b){    if(a.val != b.val)    return a.val > b.val;    else    return a.pos > b.pos;} void PushUp(int o){    sum[o] = sum[o<<1] + sum[o<<1|1];}void build(int o, int l, int r)//建树 {    sum[o] = 0;    if(l == r)    return ;     int mid = (l+r) >> 1;    build(o<<1, l, mid);    build(o<<1|1, mid+1, r);    PushUp(o);}int query(int o, int l, int r, int L, int R)//查询 {    if(L <= l && R >= r)    {        return sum[o];     }    int mid = (l+r) >> 1;    int res = 0;    if(L <= mid) res += query(o<<1, l, mid, L, R);    if(R > mid) res += query(o<<1|1, mid+1, r, L, R);    return res;}void update(int o, int l, int r, int L)//更新 {    if(l == r)     {        sum[o] += 1;        return ;    }    int mid = (l+r) >> 1;    if(L <= mid) update(o<<1, l, mid, L);    else update(o<<1|1, mid+1, r, L);     PushUp(o);}int main(){    int t, n, i;    LL ans;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        build(1, 1 ,n);        for(i = 0; i < n; i++)        {            scanf("%d", &num[i].val);            num[i].pos = i + 1;        }        sort(num, num+n, cmp);        ans = 0;        for(i = 0; i < n; i++)        {            update(1, 1, n, num[i].pos);            if(num[i].pos == 1)            continue;            ans += query(1, 1, n, 1, num[i].pos-1);        }        printf("%lld\n", ans);    }    return 0;}        

线段树(不用lazy):1384ms
 #include <cstdio>#include <cstring>#include <algorithm>#define MAX 1000000+10#define LL long longusing namespace std;int sum[MAX<<2];struct record{    int val, pos;}num[MAX];bool cmp(record a,record b){    if(a.val != b.val)    return a.val > b.val;    else    return a.pos > b.pos;} void build(int o, int l, int r)//建树 {    sum[o] = 0;    if(l == r)    return ;     int mid = (l+r) >> 1;    build(o<<1, l, mid);    build(o<<1|1, mid+1, r);}int query(int o, int l, int r, int L, int R)//查询 {    if(L == l && R == r)    {        return sum[o];     }    int mid = (l+r) >> 1;    if(R <= mid)  return query(o<<1, l, mid, L, R);    else if(L > mid)  return query(o<<1|1, mid+1, r, L, R);    else  return query(o<<1, l, mid, L, mid) + query(o<<1|1, mid+1, r, mid+1, R);}void update(int o, int l, int r, int L)//更新 {    sum[o] += 1;    if(l == r) return ;    int mid = (l+r) >> 1;    if(L <= mid) update(o<<1, l, mid, L);    else update(o<<1|1, mid+1, r, L); }int main(){    int t, n, i;    LL ans;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        build(1, 1 ,n);        for(i = 0; i < n; i++)        {            scanf("%d", &num[i].val);            num[i].pos = i + 1;        }        sort(num, num+n, cmp);        ans = 0;        for(i = 0; i < n; i++)        {            update(1, 1, n, num[i].pos);            if(num[i].pos == 1)            continue;            ans += query(1, 1, n, 1, num[i].pos-1);        }        printf("%lld\n", ans);    }    return 0;}        

树状数组:1156ms
 #include <cstdio>#include <cstring>#include <algorithm>#define LL long long#define MAX 1000000+10using namespace std;int n; int c[MAX<<2];struct record{    int val, pos;}num[MAX];bool cmp(record a,record b){    if(a.val != b.val)    return a.val > b.val;    else    return a.pos > b.pos; }int lowbit(int x){    return x&(-x);}void update(int x){    while(x <= n)    {        c[x] += 1;        x += lowbit(x);    }}LL sum(int x){    LL s = 0;    while(x > 0)    {        s += c[x];        x -= lowbit(x);    }    return s;}int main(){    int t;    int i, j;    LL ans;    //int ans;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        memset(c, 0, sizeof(c));         for(i = 0; i < n; i++)        {            scanf("%d", &num[i].val);            num[i].pos = i + 1;        }        sort(num, num+n, cmp);        ans = 0;        for(i = 0; i < n; i++)        {            update(num[i].pos);            if(num[i].pos == 1)            continue;            ans += sum(num[i].pos - 1);        }        printf("%lld\n", ans);    }    return 0;}        

归并排序:456ms
 #include <cstdio>#include <cstring>#include <algorithm>#define MAX 1000000+10#define LL long longusing namespace std;int a[MAX], tmp[MAX];LL ans;void Merge(int l, int m, int r){    int i = l;    int j = m + 1;    int k = l;    while(i <= m && j <= r)    {        if(a[i] > a[j])        {            tmp[k++] = a[j++];            ans += m - i + 1;        }        else        {            tmp[k++] = a[i++];        }    }    while(i <= m) tmp[k++] = a[i++];    while(j <= r) tmp[k++] = a[j++];    for(int i = l; i <= r; i++)    {        a[i] = tmp[i];    }}void Merge_sort(int l,int r){    if(l < r)    {        int m = (l + r) >> 1;        Merge_sort(l,m);        Merge_sort(m+1,r);        Merge(l,m,r);    }}int main(){    int t, n;    int i, j;    LL res;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        for(i = 0; i < n; i++)        {            scanf("%d", &a[i]);        }        ans = 0;        Merge_sort(0,n-1);        printf("%lld\n", ans);    }    return 0;}        

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微店没收到货却显示已收货怎么办? 手机存的照片误删了怎么办 魔兽世界把要用的装备分解了怎么办 邻居家的狗见到我就叫怎么办 我的世界玩的时间长会卡应该怎么办 网易我的世界密码账号都忘了怎么办 我的世界创建世界画面乱码了怎么办 网易我的世界云端存档不够用怎么办 玩刺激战场带耳机声音有延迟怎么办 我的世界手机版狼变色怎么办 我的世界开了光影太阳太刺眼怎么办 我的世界饥饿值掉的慢怎么办 我的世界合装备过于昂贵怎么办 我的世界故事模式屏幕是黑的怎么办 人物只剩下轮廓的图用ps怎么办 两年义务兵考军校分数不够怎么办 大学生兵考上军校后原学籍怎么办 我的世界工业附魔到精准采集怎么办 交换生在台期间遗失通行证怎么办 驾驶证上的号码是士兵证号怎么办 士兵证丢了但是要买飞机票怎么办 君泰保安公司不发工资怎么办 冬天洗棉衣后有一圈白色怎么办 买了一批化肥没有执行标准怎么办 防护栏下面打不了膨胀螺丝怎么办 不知道怀孕照了x射线怎么办 腹部照了x光片照了三次怎么办 像在工厂戴的静电帽弄丢了怎么办 诈骗犯把钱被转到别人账户怎么办 狗狗5个月在家随地大小便怎么办 上课放屁放的快没憋到老是放怎么办 丈夫有外遇并跟小三有一儿子怎么办 借款夫妻双亡借出去的钱怎么办? 橡胶底的劳保鞋开胶了怎么办? 求部队停止有偿服务内部超市怎么办 晋江买了全本还是有防盗章节怎么办 宝宝没有穿衣服的地方长疙瘩怎么办 詹姆斯士兵12魔术贴老是掉怎么办 手机版本不支持陌陌视频聊天怎么办 私人单位不给员工写收入证明怎么办 cad图形缩小后找不到图了怎么办