注意:
1.修改两个元素时不但要考虑这两个元素本身,还要考虑他们的前驱和后继结点的变化。
2.交换操作注意两个相邻元素交换是特殊情况。
3.反转整个表不需要每次都转,记录下转了多少次(转偶数次等于没转),当前如果被反转了那么1操作就会变成2操作,纸上写一下就知道了
4.输出用lld
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define maxn 100005 using namespace std; int Left[maxn]; int Right[maxn]; int n; int Start,End; int pos[maxn]; void check(int a,int b){ if(Right[a]==n+1) End=a; if(Right[b]==n+1) End=b; if(Left[a]==0) Start=a; if(Left[b]==0) Start=b; } void del(int a){ int t1=Left[a],t2=Right[a]; Left[t2]=t1; Right[t1]=t2; check(t1,t2); } void setright(int a,int b){ del(a); Left[Right[b]]=a; Right[a]=Right[b]; Right[b]=a; Left[a]=b; check(a,b); } void setleft(int a,int b){ del(a); Right[Left[b]]=a; Left[a]=Left[b]; Left[b]=a; Right[a]=b; check(a,b); } void Swap(int a,int b){ int l1=Left[a],l2=Left[b],r1=Right[a],r2=Right[b]; if(l1==b){ Left[a]=Left[b]; Left[b]=a; Right[a]=b; Right[b]=r1; Left[r1]=b; Right[l2]=a; } else if(l2==a){ Left[b]=Left[a]; Left[a]=b; Right[b]=a; Right[a]=r2; Left[r2]=a; Right[l1]=b; } else { Left[a]=l2;Left[b]=l1;Right[a]=r2;Right[b]=r1; Left[r1]=b;Right[l1]=b;Left[r2]=a;Right[l2]=a; } check(a,b); } int main(){ int flag=1; int m; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++){ Left[i]=i-1; Right[i]=i+1; } Left[0]=-1; Start=1,End=n; int flip=0; while(m--){ int t; scanf("%d",&t); if(t==1){ int a,b; scanf("%d%d",&a,&b); if(flip%2==0) setleft(a,b); else setright(a,b); } else if(t==2){ int a,b; scanf("%d%d",&a,&b); if(flip%2==0) setright(a,b); else setleft(a,b); } else if(t==3){ int a,b; scanf("%d%d",&a,&b); Swap(a,b); } else flip++; } LL res=0; if(flip%2==0){ int cur=Start; int k=1; while(cur!=n+1){ if(k%2) res+=cur; cur=Right[cur]; ++k; } } else { int cur=End; int k=1; while(cur!=0){ if(k%2) res+=cur; cur=Left[cur]; ++k; } } printf("Case %d: %lld\n",flag++,res); } return 0; }