「杂题乱刷2」CF109D

题目链接

CF109D Lucky Sorting 2000 (1800)

解题思路

我们考虑现将原序列离散化成排列,此时约束条件严格强于原题目,然后只找一个可以交换的数字,此时约束条件依然强于原题目。

那么此时我们考虑如何操作,设可以操作的数字为 id

  • 如果此时数字 i 所在的位置为 i,那么此时不需要交换。

  • 如果此时数字 i 所在的位置不为 i,且数字 id 所在的位置为 i,那么此时交换 i,id 两个数字的位置。

  • 如果此时数字 i 所在的位置不为 i,且数字 id 所在的位置不为 i,设位置 i 此时的数字为 id2,那么此时先交换 id,id2 两个数字的位置。那么此时交换 id,i 两个数字的位置。

操作次数严格不大于 2n

参考代码

ll n,id;
ll a[1000010];
ll b[1000010];
map<ll,ll>mp,mp2;
ll pos[1000010];
bool f(ll x)
{
    ll pd=1;
    while(x)
        pd&=x%10==4 || x%10==7,
        x/=10;
    return pd;
}
vector<pii>ans;
void swp(ll x,ll y)
{
    if(x==y)
        return ;
    swap(a[x],a[y]);
    swap(pos[a[x]],pos[a[y]]);
    ans.pb({x,y});
}
void _clear(){}
void solve()
{
    _clear();
    cin>>n;
    forl(i,1,n)
        cin>>a[i],
        f(a[i])?id=i:id=id;
    forr(i,n,1)
        b[i]=a[i];
    sort(b+1,b+1+n);
    ll pd=1;
    forl(i,1,n)
        pd&=a[i]==b[i];
    if(pd)
    {
        cout<<0<<endl;
        return ;
    }
    ll k=1;
    forl(i,1,n)
        mp[a[i]]++;
    for(auto i:mp)
        mp2[i.x]=k,
        k+=i.y;
    forl(i,1,n)
        a[i]=mp2[a[i]]++;
    if(id==0)
    {
        cout<<-1<<endl;
        return ;
    }
//    forl(i,1,n)
//        cout<<a[i]<<' ';
//    cout<<endl;
    forl(i,1,n)
        pos[a[i]]=i;
    id=a[id];
    forl(i,1,n)
    {
        if(pos[i]==i)
            continue;
        if(pos[id]==i)
            swp(i,pos[i]);
        else
            swp(pos[id],i),
            swp(i,pos[i]);
    }
    cout<<ans.size()<<endl;
    for(auto i:ans)
        cout<<i.x<<' '<<i.y<<endl;
}
posted @   wangmarui  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示