有如下操作:
1 x y 把x放到y的左边(相邻的左边,如果已经是左边了则忽略)
2 x y 把x放到y的右边(如果已经是右边则忽略)
3 x y 交换x,y的位置
4 反转整条链
代码如下:
#include<cstdio>
#include<iostream>
using namespace std;
#define MAX 100050
int a[MAX],r[MAX],l[MAX];
int n,m;
//a的右指针指向b,b的左指针指向a
void link(int a,int b)
{
r[a] = b;
l[b] = a;
}
int main()
{
// freopen("b.in","r",stdin);
// freopen("out.txt","w",stdout);
int t= 1;
while(scanf("%d%d",&n,&m)!=EOF)
{
r[0]=1; l[n+1]=n;
for(int i=1;i<=n;i++)
{
l[i]=i-1;
r[i]=i+1;
}
int cmd,x,y,xl,xr,yl,yr;
bool flag = false;
for(int i=1;i<=m;i++)
{
scanf("%d",&cmd);
if(cmd==4)
flag=!flag;
else
{
if(flag&&cmd!=3)
cmd = 3-cmd;
scanf("%d%d",&x,&y);
if(cmd==1)//把x放在y的左边
{
if(r[x]==y&&l[y]==x)
continue;
xl = l[x]; xr = r[x];
yl = l[y];link(xl,xr);
link(yl,x);link(x,y);
}
else if(cmd==2)//把x放在y的右边
{
if(l[x]==y&&r[y]==x)
continue;
xl = l[x]; xr = r[x];
yr = r[y]; link(xl,xr);
link(y,x); link(x,yr);
}
else//cmd==3,交换x,y的位置
{
//分情况,相邻或不相邻
//x在y左边
xl = l[x]; xr = r[x];
yr = r[y]; yl = l[y];
if(r[x]==y&&l[y]==x)
link(xl,y), link(y,x),link(x,yr);
//x在y右边
else if(l[x]==y&&r[y]==x)
link(yl,x),link(x,y),link(y,xr);
else
{
//不相邻
link(xl,y); link(y,xr);
link(yl,x); link(x,yr);
}
}
}
}
long long ans = 0;
int k = 0;
for(int i=1;i<=n;i++)
{
k = r[k];
if(i&1)
ans+=k;
}
if(flag&&(n%2==0))//偶数时改变了奇偶顺序
{
long long sum = (long long)(n/2)*(1+n);//此处一定强转不然爆int
ans = sum-ans;
}
printf("Case %d: %lld\n",t++,ans);
}
return 0;
}