题目地址:https://codeforces.com/gym/101606

这道题可以看成是CSL的魔法这道题的进阶

题意


给出初始序列。问如何将升序排列后初始序列又恢复到初始序列。

输出每次交换的位置,(A,B)且满足s[A-1]≥s[B-1],即第A个和第B个交换

 

解题思路


先将这些字符离散化,s[i].id记录每个字母的输入顺序,将输入的字符串sort后升序排列

依次遍历升序后的序列,当s[i].id!=i时说明字母在初始字符串被sort的时候位置改变了

方法1:

每次只交换两个字母,不交换字母对应的id,依照着CSL的魔法这道题中的环往下找下标,每次都与起始位置的字母交换

方法2:

每次交换两个字母和两个字母对应的id,下一次要交换的位置 :起始位置对应的id(新的id值)和起始位置

直接手动算一个例子吧:abdac

按照这两种方法输出的结果应该是

4 2
5 2
2 3

输出的结果可以不用和样例一样,毕竟方法有多种!

注意一定要满足输出的条件!!s[A-1]≥s[B-1]

ac代码


方法1:只交换字母不交换id

#include <iostream>
#include <algorithm>
#include <string.h>
#include <ctype.h>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <sstream>
#define  maxn 1005
typedef long long ll;
using namespace std;
int vis[maxn]={0};
struct node{
    char ch;
    int id;
    friend bool operator <(node a,node b)
    {
        return a.ch<b.ch;
    }
}s[maxn];
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    char s1[maxn];
    cin>>s1;
    int len=strlen(s1);
    for(int i=0;i<len;i++)
    {
        s[i].ch=s1[i];
        s[i].id=i;
    }
    sort(s,s+len);
    for(int i=0;i<len;i++)
    {
        if(s[i].id==i||vis[i]) continue;
        int start=i,next=s[start].id;
        while(next!=start)
        {
            vis[next]=1;
            if(s[start].ch>=s[next].ch)
              printf("%d %d\n",start+1,next+1);
            else
                printf("%d %d\n",next+1,start+1);
            swap(s[start].ch,s[next].ch);
            next=s[next].id;
        }
    }
    return 0;
}

方法2:交换字母和id

#include <iostream>
#include <algorithm>
#include <string.h>
#include <ctype.h>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <sstream>
#define  maxn 1005
typedef long long ll;
using namespace std;
int vis[maxn]={0};
struct node{
    char ch;
    int id;
    friend bool operator <(node a,node b)
    {
        return a.ch<b.ch;
    }
}s[maxn];
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    char s1[maxn];
    cin>>s1;
    int len=strlen(s1);
    for(int i=0;i<len;i++)
    {
        s[i].ch=s1[i];
        s[i].id=i;
    }
    sort(s,s+len);
    for(int i=0;i<len;i++)
    {
        if(s[i].id==i||vis[i]) continue;
        while(s[i].id!=i)
        {
            int now=i,next=s[now].id;
            vis[now]=1;vis[next]=1;
            if(s[now].ch>=s[next].ch)
                printf("%d %d\n",now+1,next+1);
            else if(s[next].ch>=s[now].ch)
                printf("%d %d\n",next+1,now+1);
            swap(s[now],s[next]);
        }
    }
    return 0;
}