• 洛谷 P1908 逆序对


    题目描述

    猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。

    输入输出格式

    输入格式:

    第一行,一个数n,表示序列中有n个数。

    第二行n个数,表示给定的序列。

    输出格式:

    给定序列中逆序对的数目。

    输入输出样例

    输入样例#1:
    6
    5 4 2 6 3 1
    
    输出样例#1:
    11

    说明

    对于50%的数据,n≤2500

    对于100%的数据,n≤40000。

    线段树

    屠龙宝刀点击就送

    #include <algorithm>
    #include <ctype.h>
    #include <cstdio>
    
    using namespace std;
    void read(int &x)
    {
        x=0;bool f=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-') f=1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        x=f?(~x)+1:x;
    }
    struct node
    {
        int l,r,dis;
        node *left,*right;
        node ()
        {
            left = right = NULL;
            dis = 0;
        }
    }*root;
    int data[100005],number[100005],n;
    void build(node *&k,int l,int r)
    {
        k=new node;
        k->l=l;k->r=r;
        if(l==r) {k->dis=0;return;} 
        int mid=(l+r)>>1;
        build(k->left,l,mid);
        build(k->right,mid+1,r);
    }
    int query(node *&k,int l,int r)
    {
        if(k->l==l&&k->r==r) return k->dis;
        int mid=(k->l+k->r)>>1;
        if(l>mid) return query(k->right,l,r);
        else if(r<=mid) return query(k->left,l,r);
        else return query(k->left,l,mid)+query(k->right,mid+1,r);
    }
    void signle_change(node *&k,int t)
    {
        if(k->l==k->r) {k->dis++;return;}
        int mid=(k->l+k->r)>>1;
        if(t<=mid) signle_change(k->left,t);
        else signle_change(k->right,t);
        k->dis=k->left->dis+k->right->dis;
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;i++)
        {
            read(data[i]);
            number[i]=data[i];
        }
        sort(data+1,data+1+n);
        int size=unique(data+1,data+1+n)-data-1;
        build(root,1,size);
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
            number[i]=lower_bound(data+1,data+1+size,number[i])-data;
            if(number[i]<size) ans+=query(root,number[i]+1,size);
            signle_change(root,number[i]);
        }
        printf("%lld",ans);
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    python之路1:介绍和入门
    SpringMVC学习指南【笔记3】基于注解的控制器
    SpringMVC学习指南【笔记2】简介、校验器、配置
    SpringMVC学习指南【笔记1】创建bean实例的方法和依赖注入
    2018-12-18笔记
    elastic-job简介
    Java中由于数据太大自动转换成科学计数法解决方式
    Redis主从复制
    Redis数据类型
    Redis的基本命令
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7189625.html
Copyright © 2020-2023  润新知