• HDU 6318.Swaps and Inversions-求逆序对-线段树 or 归并排序 or 离散化+树状数组 (2018 Multi-University Training Contest 2 1010)


    6318.Swaps and Inversions

    这个题就是找逆序对,然后逆序对数*min(x,y)就可以了。

    官方题解:注意到逆序对=交换相邻需要交换的次数,那么输出 逆序对个数 即可。

    求逆序对有4种操作,线段树 、BIT、归并排序、树状数组。

    我敲了线段树、归并排序和树状数组版的。

    关于这几种方法求逆序对,自行百度吧,懒了。。。

    代码(线段树版-注意排序):

     1 //1010-找逆序对数-线段树求逆序对数
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<cstdlib>
     8 #include<queue>
     9 #include<stack>
    10 using namespace std;
    11 typedef long long ll;
    12 const int inf=0x3f3f3f3f;
    13 const double eps=1e-5;
    14 const int maxn=1e5+10;
    15 #define lson l,m,rt<<1
    16 #define rson m+1,r,rt<<1|1
    17 int sum[maxn<<2];
    18 
    19 void PushUp(int rt)
    20 {
    21     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    22 }
    23 
    24 void build(int l,int r,int rt)
    25 {
    26     sum[rt]=0;
    27     if(l==r){
    28         return ;
    29     }
    30 
    31     int m=(l+r)>>1;
    32     build(lson);
    33     build(rson);
    34     PushUp(rt);
    35 }
    36 
    37 void update(int p,int l,int r,int rt)
    38 {
    39     if(l==r){
    40         sum[rt]++;
    41         return ;
    42     }
    43 
    44     int m=(l+r)>>1;
    45     if(p<=m)update(p,lson);
    46     else update(p,rson);
    47     PushUp(rt);
    48 }
    49 
    50 ll query(int L,int R,int l,int r,int rt)
    51 {
    52     if(L<=l&&r<=R){
    53         return sum[rt];
    54     }
    55     int m=(l+r)>>1;
    56     ll ret=0;
    57     if(L<=m) ret+=query(L,R,lson);
    58     if(R> m) ret+=query(L,R,rson);
    59     return ret;
    60 }
    61 
    62 int a[maxn],b[maxn];
    63 int main()
    64 {
    65     int n,x,y;
    66     while(~scanf("%d%d%d",&n,&x,&y)){
    67         build(1,n,1);
    68         for(int i=1;i<=n;i++){
    69             scanf("%d",&a[i]);
    70             b[i]=a[i];
    71         }
    72         sort(b+1,b+n+1);
    73         int len=unique(b+1,b+n+1)-b-1;
    74         for(int i=1;i<=n;i++){
    75             a[i]=upper_bound(b+1,b+len+1,a[i])-b-1;
    76         }
    77 
    78         ll sum=0;
    79         for(int i=1;i<=n;i++){
    80             sum+=query(a[i]+1,n,1,n,1);
    81             update(a[i],1,n,1);
    82         }
    83         printf("%lld
    ",sum*min(x,y));
    84     }
    85     return 0;
    86 }

    代码(归并排序版):

     1 //1010-6318-求逆序对数-归并排序
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<cstdlib>
     8 #include<cassert>
     9 using namespace std;
    10 typedef long long ll;
    11 const int maxn=1e5+10;
    12 const int inf=0x3f3f3f3f;
    13 
    14 int a[maxn],tmp[maxn];
    15 ll ans;
    16 
    17 void Merge(int l,int m,int r)
    18 {
    19     int i=l;
    20     int j=m+1;
    21     int k=l;
    22     while(i<=m&&j<=r){
    23         if(a[i]>a[j]){
    24             tmp[k++]=a[j++];
    25             ans+=m-i+1;
    26         }
    27         else{
    28             tmp[k++]=a[i++];
    29         }
    30     }
    31     while(i<=m) tmp[k++]=a[i++];
    32     while(j<=r) tmp[k++]=a[j++];
    33     for(int i=l;i<=r;i++)
    34         a[i]=tmp[i];
    35 }
    36 
    37 void Merge_sort(int l,int r)
    38 {
    39     if(l<r){
    40         int m=(l+r)>>1;
    41         Merge_sort(l,m);
    42         Merge_sort(m+1,r);
    43         Merge(l,m,r);
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     int n,x,y;
    50     while(~scanf("%d%d%d",&n,&x,&y)){
    51         memset(a,0,sizeof(a));
    52         memset(tmp,0,sizeof(tmp));
    53         for(int i=1;i<=n;i++)
    54             scanf("%d",&a[i]);
    55         ans=0;
    56         Merge_sort(1,n);
    57         printf("%lld
    ",ans*min(x,y));
    58     }
    59 }

    可以去看一下ACdreamer的博客。

    代码(离散化+树状数组):

     1 //1010-6318-求逆序对-离散化+树状数组版
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<cstdlib>
     8 #include<queue>
     9 #include<cassert>
    10 #include<map>
    11 using namespace std;
    12 typedef long long ll;
    13 const int maxn=1e5+10;
    14 
    15 int tree[maxn];
    16 int n;
    17 
    18 int lowbit(int x)
    19 {
    20     return x&(-x);
    21 }
    22 
    23 void update(int x,int val)
    24 {
    25     for(int i=x;i<=n;i+=lowbit(i)){
    26         tree[i]+=val;
    27     }
    28 }
    29 
    30 ll getsum(int x)
    31 {
    32     ll ans=0;
    33     for(int i=x;i>0;i-=lowbit(i)){
    34         ans+=tree[i];
    35     }
    36     return ans;
    37 }
    38 
    39 int a[maxn],b[maxn];
    40 map<int,int> mp;
    41 
    42 int main()
    43 {
    44     int x,y;
    45     while(~scanf("%d%d%d",&n,&x,&y)){
    46         for(int i=1;i<=n;i++){
    47             scanf("%d",&a[i]);
    48             b[i]=a[i];
    49         }
    50         sort(b+1,b+1+n);
    51         int num=1;
    52         mp.clear();
    53         for(int i=1;i<=n;i++)
    54             mp[b[i]]=num++;
    55         for(int i=1;i<=n;i++)
    56             a[i]=mp[a[i]];
    57         memset(tree,0,sizeof(tree));
    58         ll ans=0;
    59         for(int i=n;i>0;i--){
    60             ans+=getsum(a[i]-1);
    61             update(a[i],1);
    62         }
    63         printf("%lld
    ",ans*min(x,y));
    64     }
    65     return 0;
    66 }

    就这样吧,溜了。

    啊啊啊啊,cf又掉分了༼༎ຶᴗ༎ຶ༽

  • 相关阅读:
    AppDelegate生命周期详解
    Python基础数据类型
    Linux入门基础
    mac命令节选
    如何在mac下安装android sdk
    Uiatomator2 初步探索
    Uiautumator2学习,Gradle部分
    软件测试基础方法总结
    monkey测试小结
    链表中环的入口结点
  • 原文地址:https://www.cnblogs.com/ZERO-/p/9399958.html
Copyright © 2020-2023  润新知