• [蓝桥杯][历届试题]小朋友排队


    只通过比较和交换相邻两个数值的排序方法,实际上就是冒泡排序。在排序过程中每找到一对大小颠倒的相邻数值,把它们交换,就会使整个序列的逆序对个数减少(1)。最终排好序后的逆序对个数显然为(0),所以对序列进行冒泡排序需要的最少交换次数就是序列中逆序对的个数。

    本题要求计算出所有小朋友的不高兴程度之和,所有本题不是计算总的逆序对数,而是分别计算出每个位置上的数和序列中其他数所构成的逆序对数,从而得到每个位置上的不高兴程度,如果第(i)个位置和([0 sim i-1])([i+1 sim n-1])所构成的逆序对数为(k),则第(i)个位置的不高兴程度为(1 + 2 + cdots+k = frac{k(k+1)}{2})

    归并排序:

    const int N=1e5+10;
    PII a[N],temp[N];
    int cnt[N];
    int n;
    
    void merge(int l,int mid,int r)
    {
        int i=l,j=mid+1,k=0;
        while(i<=mid && j<=r)
        {
            if(a[i].fi <= a[j].fi)
            {
                cnt[a[i].se]+=j-mid-1;
                temp[k++]=a[i++];
            }
            else
            {
                cnt[a[j].se]+=mid-i+1;
                temp[k++]=a[j++];
            }
        }
    
        while(i<=mid)
        {
            cnt[a[i].se]+=j-mid-1;
            temp[k++]=a[i++];
        }
        while(j<=r)
            temp[k++]=a[j++];
        
        for(int i=0;i<k;i++) a[l+i]=temp[i];
    }
    
    void mergeSort(int l,int r)
    {
        if(l >= r) return;
    
        int mid=l+r>>1;
        mergeSort(l,mid);
        mergeSort(mid+1,r);
        merge(l,mid,r);
    }
    
    int main()
    {
        cin>>n;
    
        for(int i=0;i<n;i++)
        {
            cin>>a[i].fi;
            a[i].se=i;
        }
    
        mergeSort(0,n-1);
        
        LL res=0;
        for(int i=0;i<n;i++)
            res+=(LL)cnt[i]*(cnt[i]+1)/2;
            
        cout<<res<<endl;
        //system("pause");
        return 0;
    }
    

    树状数组:

    const int N=1e6+10;
    int c[N];
    int a[N];
    int cnt[N];
    int n;
    
    int lowbit(int x)
    {
        return x&-x;
    }
    
    void add(int x,int v)
    {
        for(int i=x;i<N;i+=lowbit(i))
            c[i]+=v;
    }
    
    int sum(int x)
    {
        int res=0;
        for(int i=x;i;i-=lowbit(i))
            res+=c[i];
        return res;
    }
    
    int main()
    {
        cin>>n;
    
        for(int i=0;i<n;i++) cin>>a[i],a[i]++;
    
        // 求每个数前面有多少个数比它大
        for(int i=0;i<n;i++)
        {
            cnt[i]+=sum(N-1)-sum(a[i]);
            add(a[i],1);
        }
    
        memset(c,0,sizeof c);
        // 求每个数后面有多少个数比它小
        for(int i=n-1;i>=0;i--)
        {
            cnt[i]+=sum(a[i]-1);
            add(a[i],1);
        }
    
        LL res=0;
        for(int i=0;i<n;i++)
            res+=(LL)cnt[i]*(cnt[i]+1)/2;
        cout<<res<<endl;
        //system("pause");
        return 0;
    }
    
  • 相关阅读:
    python-pandas
    iOS7程序内部如何打开评分页面
    iOS 7 UITableview 在Plain模式下 设置背景颜色无效
    Xcode5 运行程序 提示IOS 模拟器未能安装此应用程序
    解决 iOS7 通过tag 找不到 UITableViewCell 的子控件
    Java数据库编程及Java XML解析技术
    JavaI/O 系统
    Java图形用户界面编程
    Java中枚举的使用
    Java集合框架
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14587933.html
Copyright © 2020-2023  润新知