51Nod1574(新姿势:使序列有序的最小交换次数)

来源:互联网 发布:新时代证券交易软件 编辑:程序博客网 时间:2024/05/22 18:22

这个题按自己写的超时了,看了大神博客学习一种新姿势。

http://blog.csdn.net/f_zyj/article/details/72286343

* *  交换任意两数的本质是改变了元素位置, *  故建立元素与其目标状态应放置位置的映射关系 */int getMinSwaps(vector<int> &A){    //  排序    vector<int> B(A);    sort(B.begin(), B.end());    map<int, int> m;    int len = (int)A.size();    for (int i = 0; i < len; i++)    {        m[B[i]] = i;    //  建立每个元素与其应放位置的映射关系    }    int loops = 0;      //  循环节个数    vector<bool> flag(len, false);    //  找出循环节的个数    for (int i = 0; i < len; i++)    {        if (!flag[i])        {            int j = i;            while (!flag[j])            {                flag[j] = true;                j = m[A[j]];    //  原序列中j位置的元素在有序序列中的位置            }            loops++;        }    }    return len - loops;}vector<int> nums;int main(){    nums.push_back(1);    nums.push_back(2);    nums.push_back(4);    nums.push_back(3);    nums.push_back(5);    int res = getMinSwaps(nums);    cout << res << '\n';    return 0;}
然后这个题就按这个算法变一下就行了

#include<cstdio>#include<stack>#include<cstring>#include<algorithm>using namespace std;const int maxn = 200000+10;int p[maxn];int pos[maxn];int vis[maxn];int Scan(){    int res = 0, ch, flag = 0;    if((ch = getchar()) == '-')             //判断正负        flag = 1;    else if(ch >= '0' && ch <= '9')           //得到完整的数        res = ch - '0';    while((ch = getchar()) >= '0' && ch <= '9' )        res = res * 10 + ch - '0';    return flag ? -res : res;}int main(){    int n,a;    n = Scan();    for(int i=1;i<=n;i++) p[i] = Scan() ;    for(int i=1;i<=n;i++) {            a = Scan() ;            pos[a] = i;    }    for(int i=1;i<=n;i++)    p[i] = pos[p[i]];    long long sum = 0;    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++)    {        if(vis[i]) continue;        long long res = 0;        for(int j=i;!vis[j];j=p[j])        {            res += abs(j-p[j]);            vis[j] = 1;        }        sum += res/2;    }    printf("%lld\n",sum);    return 0;}



阅读全文
0 0