• 模板——权值线段树(逆序对)


    Ultra-QuickSort
    Time Limit: 7000MS   Memory Limit: 65536K
    Total Submissions: 62455   Accepted: 23259

    Description


    In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 
    9 1 0 5 4 ,

    Ultra-QuickSort produces the output 
    0 1 4 5 9 .

    Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

    Input

    The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

    Output

    For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

    Sample Input

    5
    9
    1
    0
    5
    4
    3
    1
    2
    3
    0
    

    Sample Output

    6
    0
    

    Source

     
    大意就是给若干个长度为n的序列求逆序对个数。
    权值线段树维护的是某个值出现的次数,所以一开始是空树(换句话说就不用建树了2333),然后不断按顺序从左到右插入点,很显然每插入一个点就记录比这个点大的个数即为此时的逆序对个数,然后累计即可。
    (其实就是用线段树维护计数数组)
    因为数值可达9亿9千9百9十9万9千9百9十9,但个数最多只有500000,所以先离散后插入。(ans要long long!!!)
     
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 int n,a[500005],tmp[500005],size;
     7 long long ans,cnt[2000005];
     8 void init(int root,int l,int r,int x){
     9     if ((l==r)&&(l==x)) {
    10         cnt[root]++;
    11         return;
    12     }
    13     int mid=(l+r)>>1;
    14     if (x<=mid) init(root<<1,l,mid,x);
    15     else if (x>mid) init(root<<1|1,mid+1,r,x);
    16     cnt[root]=cnt[root<<1]+cnt[root<<1|1];
    17 }
    18 long long sum(int root,int l,int r,int x,int y){
    19     if ((x<=l)&&(y>=r)) return cnt[root];
    20     long long anss=0;
    21     int mid=(l+r)>>1;
    22     if (x<=mid) anss+=sum(root<<1,l,mid,x,y);
    23     if (y>mid) anss+=sum(root<<1|1,mid+1,r,x,y);
    24     return anss;
    25 }
    26 int main(){
    27     scanf("%d",&n);
    28     while (n){
    29         memset(a,0,sizeof(a));
    30         memset(cnt,0,sizeof(cnt));
    31         memset(tmp,0,sizeof(tmp));
    32         size=0;
    33         ans=0;
    34         for (int i=1;i<=n;i++){
    35          scanf("%d",&a[i]);
    36          tmp[i]=a[i];
    37         }
    38         sort(tmp+1,tmp+1+n);
    39         size=unique(tmp+1,tmp+1+n)-(tmp+1);
    40         for (int i=1;i<=n;i++)
    41          a[i]=lower_bound(tmp+1,tmp+1+size,a[i])-(tmp+1)+1;
    42         for (int i=1;i<=n;i++){
    43          init(1,1,n,a[i]);
    44          ans+=sum(1,1,n,a[i]+1,n);
    45         }
    46         printf("%lld
    ",ans);
    47         scanf("%d",&n);
    48     }
    49     return 0;
    50 }
    神奇的代码
     
  • 相关阅读:
    03《高效程序员的45个习惯》阅读笔记2
    02《高效程序员的45个习惯》阅读笔记1
    关于“foreach循环”中遇到的几个问题总结
    pageContext.request.contextPath} JSP取得绝对路径
    读书笔记1
    java中字节数组byte[]和字符(字符串)之间的转换
    本学期阅读计划
    问题账户需求分析
    准备食物
    【bzoj4551】【NOIP2016模拟7.11】树
  • 原文地址:https://www.cnblogs.com/Lanly/p/7327844.html
Copyright © 2020-2023  润新知