题意:有n个箱子,编号1~n,有4中操作:把a移到b左边,把a移到b右边,交换ab,倒置所有箱子的顺序。操作完后输出第奇数个箱子的编号和。
思路:双向链表。这题写得真是蛋疼,有一点小bug,一直发现不了,WA和TLE了不下20次。题虽然不难,但是需要非常细心。另外提一个技巧,像倒置这种费时的操作,并不需要真正模拟。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 1000000010
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 1000
using namespace std;
int l[100010];
int r[100010];
inline void link(int a,int b){
r[a]=b;
l[b]=a;
}
int main(){
int n,m;
int _case=0;
while(~scanf("%d%d",&n,&m)){
_case++;
for(int i=1;i<=n;i++){
l[i]=i-1;
r[i]=(i+1)%(n+1);
}
r[0]=1;
l[0]=n;
bool rev=false;
for(int i=1;i<=m;i++){
int o;
scanf("%d",&o);
if(o==4){
rev=!rev;
}else{
int a,b;
scanf("%d%d",&a,&b);
if(rev&&o!=3)o=3-o;
// if(o==3&&r[b]==a)swap(a,b);
if(o==1){
int la=l[a];
int ra=r[a];
int lb=l[b];
int rb=r[b];
if(ra==b)continue;
link(la,ra);
link(lb,a);
link(a,b);
}
if(o==2){
int la=l[a];
int ra=r[a];
int lb=l[b];
int rb=r[b];
if(rb==a)continue;
link(la,ra);
link(b,a);
link(a,rb);
}
if(o==3){
int la=l[a];
int ra=r[a];
int lb=l[b];
int rb=r[b];
if(ra==b){
link(la,b);
link(b,a);
link(a,rb);
continue;
}
if(rb==a){
link(lb,a);
link(a,b);
link(b,ra);
continue;
}
link(la,b);
link(b,ra);
link(lb,a);
link(a,rb);
}
}
}
ll ans=0;
int t=r[0];
int cnt=0;
int nn=n;
while(nn--){
// cout<<t<<" ";
cnt++;
if(cnt&1)ans+=t;
t=r[t];
}
if(rev&&n%2==0)ans=(ll)n*(n+1)/2-ans;
printf("Case %d: %lld\n",_case,ans);
}
return 0;
}