• 线段树求逆序数+北化校赛D题


    Ultra-QuickSort

     OpenJ_Bailian - 2299 

    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.InputThe 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.OutputFor 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
    思路:对于每次输入的数据,即刻判断其前面比它大的数的个数,范围是当前这个数+1,到最大值,然后立刻更新。因为数据很大,需要离散化,具体看代码。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e6;
    struct node{
        int l;
        int r;
        int sum;
    }e[maxn<<2];
    struct tree{
        int pos;
    }tree[maxn<<2];
    long long sum;
    int mp[maxn];
    int a[maxn],n;
    void build(int l,int r,int cur)
    {
        e[cur].l=l;
        e[cur].r=r;
        e[cur].sum=0;
        if(l==r)
            return;
        int mid=(l+r)/2;
        build(l,mid,cur<<1);
        build(mid+1,r,cur<<1|1);
    }
    void pushup(int cur)
    {
        e[cur].sum=e[cur<<1].sum+e[cur<<1|1].sum;
    } 
    int query(int pl,int pr,int cur)
    {
        if(pl<=e[cur].l&&e[cur].r<=pr)
        {
            return e[cur].sum;
        }
        int mid=(e[cur].l+e[cur].r)/2;
        int res=0;
        if(pl<=mid)
             res+=query(pl,pr,cur<<1);
        if(pr>mid)
            res+=query(pl,pr,cur<<1|1);
        return res;
    }
    void update(int tar,int cur)
    {
        if(e[cur].l==e[cur].r)
        {
            e[cur].sum++;
            return;
        }
        int mid=(e[cur].l+e[cur].r)/2;
        if(tar<=mid)
            update(tar,cur<<1);
        else
            update(tar,cur<<1|1);
        pushup(cur);
    }
    int main()
    {
        while(~scanf("%d",&n)&&n)
        {
            memset(mp,0,sizeof(mp));
            memset(a,0,sizeof(a)); 
            sum=0;
            build(1,maxn,1);
            int t=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                mp[++t]=a[i];
            } 
            sort(mp+1,mp+t+1);
            int cnt=1;
            int R;
            
            for(int i=2;i<=t;i++)
            {
                if(mp[i]!=mp[i-1])
                {
                    mp[++cnt]=mp[i];
                }
            }
            for(int i=1;i<=n;i++)
            {
                int ul=lower_bound(mp+1,mp+1+cnt,a[i])-mp;
                tree[i].pos=ul;
            //    cout<<ul<<endl;
            } 
            for(int i=1;i<=n;i++)
            {
                sum+=query(tree[i].pos+1,maxn,1);    
                update(tree[i].pos,1);
            }
            printf("%lld
    ",sum);
        }
        
    } 

    Minimum Inversion Number

     HDU - 1394 

     

    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. 

    For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following: 

    a1, a2, ..., an-1, an (where m = 0 - the initial seqence) 
    a2, a3, ..., an, a1 (where m = 1) 
    a3, a4, ..., an, a1, a2 (where m = 2) 
    ... 
    an, a1, a2, ..., an-1 (where m = n-1) 

    You are asked to write a program to find the minimum inversion number out of the above sequences. 

    InputThe input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1. 
    OutputFor each case, output the minimum inversion number on a single line. 
    Sample Input

    10
    1 3 6 9 0 8 5 7 4 2

    Sample Output

    16
    题意:将一组数循环后移,问逆序数的最少为多少
    题解:1、对于某一序列,其中的某一个数a[i]能构成多少个逆序,只须判断在a[i]+1~n的范围内找之前的数是否出现过的次数; 2、然后求出第一个序列的逆序数。 3、由第一个序列的逆序数可以推出它下一个序列的逆序数。 有规律 下一个序列的逆序数 sum = 上一个的sum - a[i] - 1- a[i];如果得出呢 比如说: 序列 3 6 9 0 8 5 7 4 2 1 把3移到后面,则它的逆序数会减少3个(0 2 1) 但同时会增加 n - a[i] - 1个。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define inf 99999999999
     6 using namespace std;
     7 const int maxn=5010;
     8 typedef long long ll;
     9 int n;
    10 struct node{
    11     int l;
    12     int r;
    13     int sum;
    14 }e[maxn<<2];
    15 int a[maxn<<2];
    16 void build(int l,int r,int cur)
    17 {
    18     e[cur].l=l;
    19     e[cur].r=r;
    20     e[cur].sum=0;
    21     if(l==r)
    22         return;
    23     int mid=(l+r)/2;
    24     build(l,mid,cur<<1);
    25     build(mid+1,r,cur<<1|1);
    26 }
    27 ll query(int pl,int pr,int cur)
    28 {
    29     if(pl<=e[cur].l&&e[cur].r<=pr)
    30     {
    31         return e[cur].sum;
    32     }
    33     ll res=0;
    34     int mid=(e[cur].l+e[cur].r)/2;
    35     if(pl<=mid)
    36         res+=query(pl,pr,cur<<1);
    37     if(pr>mid)
    38         res+=query(pl,pr,cur<<1|1);
    39 return res;    
    40 }
    41 void update(int tar,int cur)
    42 {
    43     if(e[cur].l==e[cur].r)
    44     {
    45         e[cur].sum++;
    46         return ;
    47     }
    48     int mid=(e[cur].l+e[cur].r)/2;
    49     if(tar<=mid)
    50         update(tar,cur<<1);
    51     else
    52         update(tar,cur<<1|1);
    53     e[cur].sum=e[cur<<1].sum+e[cur<<1|1].sum;
    54 }
    55 int main()
    56 {
    57     while(~scanf("%d",&n))
    58     {
    59         int t=n;
    60         ll res=0;build(0,n,1);
    61         memset(a,0,sizeof(a));
    62         for(int i=0;i<n;i++)
    63         {
    64             scanf("%d",&a[i]);
    65             res+=query(a[i]+1,n,1);
    66             update(a[i],1);
    67         }
    68         int k=0;
    69         ll ans=inf;
    70         ans=res;  
    71         for(int i=0;i<n;++i) {  
    72             res=res-a[i]+(n-1-a[i]);  
    73             ans=min(ans,res);  
    74         }  
    75         printf("%lld
    ",ans);
    76     } 
    77     
    78 }
     

    问题 D: 积木

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    我懒得编故事了  m哥牛逼! 
    有n个积木,第i个积木的高度为a[i],求每个积木前面有几个比它矮的积木 

    输入

    
    
    多组输入,每组由两行组成,第一行输入n,第二行输入n个数,为n个积木的高度a[i] 
    //(1<=n<=100000)(1<=a[i]<=1000000000) 

    输出

    每组数据输出n个数,第i个数为第i个积木前面比他矮的积木的个数

    样例输入

    5
    1 2 3 4 5

    样例输出

    0 1 2 3 4
    
    

     注意:多组输入~~~~~~~

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 typedef long long ll;
      7 const int maxn=1e5+10;
      8 struct node{
      9     ll l;
     10     ll r;
     11     long long sum;
     12 }e[maxn<<2];
     13 long long ans[maxn<<2];
     14 struct tree{
     15     ll pos;
     16 }tree[maxn<<2];
     17 long long sum;
     18 long long  mp[maxn];
     19 long long  a[maxn],n;
     20 void build(ll l,ll r,ll cur)
     21 {
     22     e[cur].l=l;
     23     e[cur].r=r;
     24     e[cur].sum=0;
     25     if(l==r)
     26         return;
     27     ll mid=(l+r)/2;
     28     build(l,mid,cur<<1);
     29     build(mid+1,r,cur<<1|1);
     30 }
     31 void pushup(ll cur)
     32 {
     33     e[cur].sum=e[cur<<1].sum+e[cur<<1|1].sum;
     34 }
     35 ll query(ll pl,ll pr,ll cur)
     36 {
     37     if(pl<=e[cur].l&&e[cur].r<=pr)
     38     {
     39         return e[cur].sum;
     40     }
     41     ll mid=(e[cur].l+e[cur].r)/2;
     42     ll res=0;
     43     if(pl<=mid)
     44          res+=query(pl,pr,cur<<1);
     45     if(pr>mid)
     46         res+=query(pl,pr,cur<<1|1);
     47     return res;
     48 }
     49 void update(long long  tar,ll cur)
     50 {
     51     if(e[cur].l==e[cur].r)
     52     {
     53         e[cur].sum++;
     54         return;
     55     }
     56     ll mid=(e[cur].l+e[cur].r)/2;
     57     if(tar<=mid)
     58         update(tar,cur<<1);
     59     else
     60         update(tar,cur<<1|1);
     61     pushup(cur);
     62 }
     63 int main()
     64 {
     65     while(~scanf("%lld",&n))
     66     {
     67          sum=0;
     68         build(1,maxn,1);
     69         ll t=0;
     70         for(ll i=1;i<=n;i++)
     71         {
     72             scanf("%lld",&a[i]);
     73             mp[++t]=a[i];
     74         }
     75         sort(mp+1,mp+t+1);
     76         ll cnt=1;
     77         ll R;
     78 
     79         for(ll i=2;i<=t;i++)
     80         {
     81             if(mp[i]!=mp[i-1])
     82             {
     83                 mp[++cnt]=mp[i];
     84             }
     85         }
     86         for(ll i=1;i<=n;i++)
     87         {
     88             ll ul=lower_bound(mp+1,mp+1+cnt,a[i])-mp;
     89             tree[i].pos=ul;
     90         //    cout<<ul<<endl;
     91         }
     92         for(ll i=1;i<=n;i++)
     93         {
     94             sum+=query(1,tree[i].pos-1,1);
     95             ans[i]=sum;
     96             //printf("%lld ",sum);
     97             update(tree[i].pos,1);
     98         }
     99         for(ll i=1;i<n;i++)
    100         {
    101             printf("%lld ",ans[i]-ans[i-1]);
    102         }
    103         printf("%lld
    ",ans[n]-ans[n-1]);
    104 
    105        // printf("%lld
    ",sum);
    106     }
    107 
    108 }
    
    
  • 相关阅读:
    Java中的List转换成JSON报错(一)
    关于侦听的注册
    TCMalloc小记
    ocp|ocm考证系列文章
    开源HTML5 APP开发神器CanTK发布
    实例级别的回滚
    MySQL查询所有数据库表出错
    java.lang.ArrayIndexOutOfBoundsException
    如何修改64位Eclipse中的代码字体大小
    gpt 分区容量错误
  • 原文地址:https://www.cnblogs.com/1013star/p/9709556.html
Copyright © 2020-2023  润新知