洛谷P1327 数列排序 数学 图论

洛谷P1327 数列排序

数学   图论

这道题其实 就是求 排序前以及排序后的连通块 冲突减连边 ,因为交换的都是在那个连通块中的,这样就能保证最优
这样连通块中有 n 个点,就是要交换 n-1 次
但是 我写的常数 非常丑 结果洛谷上T了一个点 开心

将序列排序

找出所有的循环,即错误位置调换的循环

如 2 4 1 3 循环为 2->4->3->1->2

(手写快排累死了)

代码 (减少代码复制,创建美好洛谷)

 

 

 1 #include <cstdio>                    //   90 分
 2 #include <algorithm>
 3 #include <map>
 4 using namespace std ; 
 5 
 6 const int maxn = 100011,inf = 1000 ;
 7 int n,ans ;  
 8 int a[maxn],b[maxn] ; 
 9 map <int,bool> f ; 
10 
11 inline int dfs(int u) 
12 {
13     int sum = 1 ;
14     int x = 0,y = 0 ; 
15     if( f.count(a[ u ]) )  return 0 ; 
16     f[ a[ u ] ] = 1 ; 
17     while(1) 
18     {
19         x = a[ u ] ; 
20         u = lower_bound(b+1,b+n+1,x) - b ;  
21         if(  f.count(a[ u ]) ) break ;
22         sum++ ; 
23         f[ a[ u ] ] = 1 ;
24     }
25     return sum - 1 ; 
26     
27 }
28 
29 int main() 
30 {
31     scanf("%d",&n) ;  
32     for(int i=1;i<=n;i++) scanf("%d",&a[ i ]),b[ i ] = a[ i ] ;  
33     sort(b+1,b+n+1) ;  
34     for(int i=1;i<=n;i++) 
35         if(a[ i ]==b[ i ]) continue ;
36             else ans+=dfs( i ) ; 
37     printf("%d",ans) ; 
38     
39     return 0 ; 
40 }

 

 

代码的优化 
1、将对值的布尔转成对 原来下标的布尔 ,这样少掉一只map
2、快排时直接处理 快排前与快排后 少掉 二分 lower_bound 
3、手打快排 优化常数


这样优化了之后就能 过了 

 

 

 1 #include<iostream>             
 2 #include<cstring>  
 3 using namespace std;  
 4 int n,a[100001],b[100001],ans,x,tot;       //  ac 程序
 5 bool flag[100001];  
 6 void kp(int l,int r)  
 7 {  
 8     int i=l,j=r,x,t;  
 9     x=a[(i+j)/2];  
10     while(i<=j)  
11     {  
12       while (a[i]<x) i++;  
13       while (a[j]>x) j--;  
14       if (i<=j)  
15       {t=a[i];a[i]=a[j];a[j]=t;  
16        t=b[i];b[i]=b[j];b[j]=t;i++;j--;}  
17     }  
18     if (l<j) kp(l,j);  
19     if (i<r) kp(i,r);  
20 }  
21 int main()  
22 {  
23     memset(flag,false,sizeof(flag));  
24     cin >> n;  
25     for(int o=1;o<=n;o++)  
26     {  
27       cin >> a[o];  
28       b[o]=o;  
29     }  
30     kp(1,n);  
31     for(int i=1;i<=n;i++)  
32       if(!flag[i])  
33       {  
34           x=i;tot=0;  
35           while(!flag[x])  
36           {  
37             flag[x]=true;  
38             tot++;  
39             x=b[x];  
40           }  
41           ans+=tot-1;  
42       }  
43     cout << ans;  
44     return 0;  
45 }

 

转载于:https://www.cnblogs.com/third2333/p/6933321.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值