Problem Description
给你n和m,分别对应1-n的编号,和m行操作,有四种情况1 X Y:X移动到Y的左边, 2 X Y: X移动到Y的右边, 3 X Y:交换位置, 4 反转整个编号。
代码:
#include<bits/stdc++.h>
using namespace std;
int lt[100055];//记录i点的左边下标
int rt[100055];//记录i点的右边下标
void link(int L, int R)//连接L,R,L在左边R在右边的连接方式
{
rt[L] = R;
lt[R] = L;
}
int main()
{
int n, m, cas = 1;
while(~scanf("%d %d", &n, &m))
{
for(int i = 1; i <= n; i++)//初始化记录
{
rt[i] = (i + 1) % (n + 1);
lt[i] = i - 1;
}
rt[0] = 1; lt[0] = n;
int op, x, y, inv = 0;
while(m--)
{
scanf("%d", &op);
if(op == 4) inv = !inv;//标记反转
else
{
scanf("%d %d", &x, &y);
if(op != 3 && inv) op = 3 - op; //如果反转 1 变为2, 2 变为1
if(op == 1 && x == lt[y]) continue;
if(op == 2 && x == rt[y]) continue;
int Lx = lt[x], Rx = rt[x], Ly = lt[y], Ry = rt[y];
if(op == 1)//x到y的左边
{
link(Lx, Rx); link(Ly, x); link(x, y);
}
else if(op == 2)//x到y的右边
{
link(Lx, Rx); link(x, Ry); link(y, x);
}
else if(op == 3)//交换位置
{
if(rt[y] == x)//相邻
{
link(Ly, x); link(x, y); link(y, Rx);
}
else if(rt[x] == y)//相邻
{
link(Lx, y); link(y, x); link(x, Ry);
}
else//不相邻
{
link(Lx, y); link(y, Rx); link(Ly, x); link(x, Ry);
}
}
}
}
int b = 0;
long long ans = 0;
for(int i = 1; i <= n; i++)
{
b = rt[b];
if(i % 2 != 0) ans += b;
}
if(inv && n % 2 == 0) ans = (long long) n * (n + 1) / 2 - ans;//n为奇数求和结果不变
printf("Case %d: %lld\n", cas++, ans);
}
}