Description
你有一行盒子,从左到右依次编号为1, 2, 3,…, n。你可以执行四种指令:
1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令)。
2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此指令)。
3 X Y表示交换盒子X和Y的位置。
4 表示反转整条链。
指令保证合法,即X不等于Y。例如,当n=6时在初始状态下执行1 1 4后,盒子序列为2 3 1 4 5 6。接下来执行2 3 5,盒子序列变成2 1 4 5 3 6。再执行3 1 6,得到2 6 4 5 3 1。最终执行4,得到1 3 5 4 6 2。
Input
输入包含不超过10组数据,每组数据第一行为盒子个数n和指令条数m(1<=n,m<=100,000),以下m行每行包含一条指令。
Output
每组数据输出一行,即所有奇数位置的盒子编号之和。位置从左到右编号为1~n。
Sample Input
6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4
Sample Output
Case 1: 12
Case 2: 9
你有一行盒子,从左到右依次编号为1, 2, 3,…, n。你可以执行四种指令:
1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令)。
2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此指令)。
3 X Y表示交换盒子X和Y的位置。
4 表示反转整条链。
指令保证合法,即X不等于Y。例如,当n=6时在初始状态下执行1 1 4后,盒子序列为2 3 1 4 5 6。接下来执行2 3 5,盒子序列变成2 1 4 5 3 6。再执行3 1 6,得到2 6 4 5 3 1。最终执行4,得到1 3 5 4 6 2。
Input
输入包含不超过10组数据,每组数据第一行为盒子个数n和指令条数m(1<=n,m<=100,000),以下m行每行包含一条指令。
Output
每组数据输出一行,即所有奇数位置的盒子编号之和。位置从左到右编号为1~n。
Sample Input
6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4
Sample Output
Case 1: 12
Case 2: 9
Case 3: 2500050000
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1001000
#define ll long long
using namespace std;
int nex[maxn],pre[maxn],n,m,k,tim;
int *tep,*tep2;
void init_nex_pre()
{
for (int i=1; i<=n; i++)
nex[i]=i+1,pre[i]=i-1;
nex[n]=0;
}
void dele(int x)
{
int k1=pre[x],k2=nex[x];
nex[k1]=k2,pre[k2]=k1;
}
void inser(int k1,int mid,int k2)
{
nex[k1]=mid,nex[mid]=k2;
pre[k2]=mid,pre[mid]=k1;
}
void SWAP(int x,int y)
{
int k1=pre[x],k2=nex[x],k3=pre[y],k4=nex[y];
if (k2==y)//考虑xy相邻的情况
{
nex[k1]=y,nex[y]=x,nex[x]=k4;
pre[k4]=x,pre[x]=y,pre[y]=k1;
}
else if (k4==x)//考虑xy相邻的情况
{
nex[k3]=x,nex[x]=y,nex[y]=k2;
pre[k2]=y,pre[y]=x,pre[x]=k3;
}
else
{
nex[k1]=y,nex[y]=k2,pre[y]=k1,pre[k2]=y;
nex[k3]=x,nex[x]=k4,pre[x]=k3,pre[k4]=x;
}
}
int main()
{
int cod,x,y,cas=0;
while (cin>>n>>m)
{
tim=0;
init_nex_pre();///初始
while (m--)
{
cin>>cod;///输入操作
if (cod==4)
tim++;//这里只要记录首位交换了多少次哦
else
{
cin>>x>>y; ///输入即将进行的转换
if (cod<3 && tim&1)///如果code<3且time为奇数
cod=3-cod;//如果交换了奇数次,那么本来应该插在前面就相当于是现在应该插在后面,
//T_T不好怎么表达,自己理解一下就懂了。
if (cod==1)
{
dele(x);
k=pre[y];
inser(k,x,y); ///x插在y左边
}
else if (cod==2)
{
dele(x);
k=nex[y];
inser(y,x,k); ///x插在y右边
}
else if (cod==3) SWAP(x,y); ///交换
}
}
if (tim&1) ///如果4交换的是奇数次
tep=pre,tep2=nex;
else
tep=nex,tep2=pre;///偶数次的话
for (int i=1; i<=n; i++)
{
if (tep2[i]==0)
{
ll ans=0;
for (int k=1; i; i=tep[i],k++)
{
if (k&1)///转化为二进制的低位与1相与,如果为1 则为k为奇数
ans+=i;
}
cout<<"Case "<<++cas<<": "<<ans<<endl;
break;
}
}
}
return 0;
}