题目链接

https://ac.nowcoder.com/acm/contest/8564/F

解题思路

很多同学是不是没理解题目,画个图(其中f表示翻转次数,f=1表示翻转奇数次,f=0表示翻转偶数次):
图片说明


大致思路:
数据结构啊,用结构体数组模拟链表。因为涉及类似节点移动的操作,用线性表时间复杂度太高,这时候链表的优势就发挥出来了。模拟过程就好。
详细思路:
建立结构体数组information[i],内含两个变量before和after,分别指向i节点的前面节点和后面节点;
注:我们模拟的时候是不进行彻头彻尾的翻转操作的,因为太浪费时间了,我们不妨记录下来是否发生了翻转,翻转后的插入操作是将“x插于y前”“x插于y后”分别变成了“x插于y后”“x插于y前”;翻转前的插入操作正常进行。
输出的时候,当f=1时,我们输出before,相当于逆时针输出;当f=0时,我们输出after,相当于顺时针输出。

抱歉,我表达能力太差了……
稍微说一下,我当时是怎么想到的:
首先想到用结构体模拟链表;
之后,觉得题目让怎么插入我就怎么修改,直接记录下来是否翻转(就是翻转次数的奇偶),输出的时候根据标记选择顺时针输出还是逆时针输出就ok了。
但是,wa了,举了个反例发现了错误,比如先进行翻转操作,再进行移动操作,发现与正确的输出有差别。
而且发现差别不大,仿佛就是翻转后导致插入的时候有点问题,我就将“向后/前插”调整为“向前/后插”,完美AC!
我感觉这里才是最难想的地方。至于移动操作,虽然代码长,但是我觉得学过数据结构的应该都能自己写,反而看别人的代码可能理解起来更慢。

AC代码

#include<bits/stdc++.h>
#define ll long long

using namespace std;
const int N=1e4+100;

int f,n,m,op,x,y,tt,pp;
struct INF
{
    int be,af;    
}inf[N];

/*
//for testing

void output()
{
    int mm=n,pp=1;
    while(mm--)
    {
        printf("%d%c",pp,mm?' ':'\n');
        pp=inf[pp].af;
    }
}
*/

void putbefore(int,int,int);//提前声明一下,要不编译不了 
void putafter(int ff,int xx,int yy)
{
    if(ff) putbefore(0,xx,yy);//发生过翻转后把x放到y后面 相当于 发生翻转前把x放到y前面,输出时能保证是正确的 
    //这里把f当成参数传入是防止putbefore和putafter循环调用导致死循环,下同 
    else
    {
        inf[inf[x].af].be=inf[x].be;//让x的 后继节点 的 前驱节点指针 指向x的 前驱节点 
        inf[inf[x].be].af=inf[x].af;//让x的 前驱节点 的 后继节点指针 指向x的 后继节点 
        inf[x].af=inf[y].af;//让x的 后继节点指针 指向y的 后继节点 
        inf[x].be=y;//让x的 前驱节点指针 指向y 
        inf[inf[y].af].be=x;//让y的 后继节点 的 前驱节点指针 指向x 
        inf[y].af=x;//让y的 后继节点指针 指向x 
    }
}
void putbefore(int ff,int xx,int yy)
{
    if(ff) putafter(0,xx,yy);//发生过翻转后把x放到y前面 相当于 发生翻转前把x放到y后面,输出时能保证是正确的 
    else 
    {
        //类似与上面 
        inf[inf[x].af].be=inf[x].be;
        inf[inf[x].be].af=inf[x].af;
        inf[x].be=inf[y].be;
        inf[x].af=y;
        inf[inf[y].be].af=x;
        inf[y].be=x;
    }
}
int main()
{
    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;i++) inf[i].be=(i==1?n:i-1),inf[i].af=(i==n?1:i+1);//初始化 

//    for(int i=1;i<=n;i++) cout<<i<<' '<<inf[i].be<<' '<<inf[i].af<<endl;//for testing

    while(m--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d",&x,&y);
            putafter(f,x,y);//把x放到y的后面,但是要注意是否发生翻转,详见函数代码注释 

        //    for(int i=1;i<=n;i++) cout<<i<<' '<<inf[i].be<<' '<<inf[i].af<<endl;//for testing
        //    output();//for testing

        }
        else if(op==2) 
        {
            scanf("%d%d",&x,&y);
            putbefore(f,x,y);//把x放到y的前面,但是要注意是否发生翻转,详见函数代码注释

        //    for(int i=1;i<=n;i++) cout<<i<<' '<<inf[i].be<<' '<<inf[i].af<<endl;//for testing
        //    output(); //for testing

        }
        else if(op==3) //reverse
        {
            f^=1;//标记翻转 
        }
        else //print
        {
            tt=n;pp=1;
            if(f) 
            {
                while(tt--)
                {    
                    printf("%d%c",pp,tt?' ':'\n');
                    pp=inf[pp].be;//发生过奇数次翻转,从1开始向前输出,或者说逆时针输出 
                }
            }
            else 
            {
                while(tt--)
                {
                    printf("%d%c",pp,tt?' ':'\n');
                    pp=inf[pp].af;//发生过偶数次翻转,从1开始向后输出,或者说顺时针输出 
                }
            }
        }
    }
}