题意:在一排盒子,最初从小到大,记过以下有4个操作,求奇数位置的和。
1 X Y : move box X to the left to Y (ignore this if X is already the left of Y )
2 X Y : move box X to the right to Y (ignore this if X is already the right of Y )
3 X Y : swap box X and Y
4: reverse the whole line.
思路:像uva11988,只用一个next表示左右相邻的关系,不够,这里突出左右两边的关系,解决办法是,用数组模拟双向链表,left[],right[],详细过程见代码。学习了用数组模拟双向链表,
比如 相连接
void Link(int L,int R){ right[L]=r,left[R]=l;}
#include <fstream> #include <iostream> #include <string> #include <cstring> #include <complex> #include <math.h> #include <set> #include <vector> #include <map> #include <queue> #include <stdio.h> #include <stack> #include <algorithm> #include <list> #include <ctime> #include <ctime> #include <assert.h> #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define eps 1e-8 #define M_PI 3.141592653589793 typedef long long ll; const ll mod=1000000007; const int inf=0x7fffffff; ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} using namespace std; int a[110000],L[110000],R[110000]; void Link(int l,int r) { L[r]=l;R[l]=r; } int main() { int n,m,cnt=0; while(~scanf("%d %d",&n,&m)){ //for(int i=0;i<=n;i++) a[i]=i; for(int i=1;i<=n;i++){ L[i]=i-1;R[i]=(i+1)%(n+1); } L[0]=n,R[0]=1; int op,flag=0,x,y; for(int i=1;i<=m;i++){ scanf("%d",&op); if(op==4) flag=!flag; else { scanf("%d %d",&x,&y); if(op!=3&&flag==1) op=3-op; if(op==3&&R[y]==x) swap(x,y); if(op==1&&L[y]==x) continue; if(op==2&&R[y]==x) continue; int Lx=L[x],Ly=L[y],Rx=R[x],Ry=R[y]; if(op==1){ Link(Lx,Rx);Link(Ly,x);Link(x,y); } else if(op==2){ Link(Lx,Rx);Link(y,x);Link(x,Ry); } else if(op==3){ if(R[x]==y){ Link(Lx,y);Link(y,x);Link(x,Ry); } else{ Link(Lx,y);Link(y,Rx);Link(Ly,x);Link(x,Ry); } } } } ll res=0; int t=1; for(int i=R[0];i!=0;i=R[i]){ //cout<<i<<" "; if(t%2==1) res+=i; t++; } if(flag&&n%2==0) res=(ll)n*(n+1)/2-res; printf("Case %d: %lld\n",++cnt,res); } }