CF 109D 模拟

题目不要求k最小,所以定住一个lucky number,反复用它进行交换。最后的结果必须是不降序,所以先确定每个位置上最终的数,若当前此位不是最终结果,就进行交换。例如第i位,若第i位上的数不满足最终结果,就用它与lucky number交换,再用lucky number和最终应该在第i位上的数交换,一共两次。这样最多交换(n-1)回合,正好满足题意交换次数<=2n。。。看似很简单,写起来很费劲,错误满篇,不得不说自己too young too simple~~~~~

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>

#define N 100004
#define cl(a) memset(a,0,sizeof(a))
#define pb push_back

using namespace std;

int a[N],r[N],b[N];
vector<int>c1,c2;

int check(int x)
{
    while (x>0)
    {
        if (x%10!=4&&x%10!=7) return 0;
        x/=10; 
    }
    return 1;
}

int bin(int key,int l,int r)
{
    if (r-l<=1)
    {
        if (b[l]==key) return l;
        else return r;
    }
    int m=(l+r)/2;
    if (key>b[m]) return bin(key,m+1,r);
    else return bin(key,l,m);
}

void swaping(int p,int q)
{
    int sw=a[q];
    a[q]=a[p];
    a[p]=sw;
    c1.pb(p);
    c2.pb(q);
}

int main()
{
    int i,n,l=-1,k,f;
    while (cin>>n)
    {
        for (i=1;i<=n;i++)
        {
            cin>>a[i];
            b[i]=a[i];
            if (l<0)
            {
                if (check(a[i])) l=i; 
            }
        }
        sort(b+1,b+n+1);
        if (l<0) 
        {
            for (i=1;i<=n;i++) if (a[i]!=b[i]) break;  
            if (i>n) cout<<0<<endl;
            else cout<<-1<<endl;
            continue;
        }
        for (i=1;i<=n;i++)
        {
            k=bin(a[i],1,n);
            while (r[k]) k++;
            r[k]=i;
            if (i==l) f=k;
        } 
        for (i=1;i<=n;i++) a[r[i]]=i;
        for (i=1;i<=n;i++)
        {
            if (a[i]!=i&&i!=f)
            {
                int t=a[i],l0=l;
                if (i!=l) 
                {
                    swaping(i,l);
                    r[t]=l;l0=i;
                }
                if (r[i]!=l0) 
                {
                    swaping(i,r[i]);
                    l0=r[i];
                }
                l=l0;
            }
        }
        cout<<c1.size()<<endl;
        for (i=0;i<c1.size();i++)
            cout<<c1[i]<<" "<<c2[i]<<endl;
    }
    return 0;
}


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值