Uva 12657 Boxes in a Line 双向链表

  • 操作4比较特殊,为了避免一次性修改所有元素的指针,由于题目只要求输出奇数盒子的编号,所以我们可以灵活的根据是否进行过操作4对操作1 操作2 进行改动
  • 操作3不受操作4影响

上代码。。。。

#include<cstdio>
#include<algorithm>
const int maxn=100000+5;
int right[maxn],left[maxn];
void link (int L,int R){
	right[L]=R;left[R]=L;
}
//在双向链表这样复杂的数据结构中,往往会编写一些辅助函数来设置链接关系
int main(){
	int m,n,kase=0;
	while(scanf("%d%d",&n,&m)==2){
      for(int i=1;i<=n;i++){
        right[i]=(i+1)%(n+1);
	    left[i]=i-1;
      }
	  right[0]=1;left[0]=n;
	  int op,x,y,flag=0;
	  while(m--){
		scanf("%d",&op);
		if (op==4) flag=!flag;//操作4是否执行奇数次
		else{
            scanf("%d%d",&x,&y);
		    if(op==3&&right[y]==x) std::swap(x,y);//为了方便操作,避免重写第37行代码,当然你重写也可以
		    if(op!=3&&flag) op=3-op;
		    if(op==1&&x==left[y]) continue;//如果x已经在y的左边则忽略此指令
		    if(op==2&&x==right[y]) continue;//如果x已经在y的右边则忽略此指令
		    int lx=left[x],rx=right[x],ly=left[y],ry=right[y];
		    if(op==1){
			  //插入到x的左边并删除原来x结点的位置
			  link(lx,rx);link(ly,x);link(x,y);
		    }
		    else if (op==2){
			  //插入到y的右边并删除原来x结点的位置
			  link(lx,rx);link(y,x);link(x,ry);
		    }
		    else if(op==3){
			 if(right[x]==y){link(lx,y);link(y,x);link(x,ry);
			 }
			 else {
              link(lx,y);link(y,rx);//y插入到x的位置
              link(ly,x);link(x,ry);//x插入到y的位置
			 }
		     }
	    }
	  }
	    int b=0;
	    long long ans=0;
	    for (int i=1;i<=n;i++){
		    b=right[b];
		    if(i&1) ans+=b;
	    }
	    if(flag&&n%2==0) ans=(long long)n*(n+1)/2-ans;
	    printf("Case %d: %lld\n",++kase,ans);
    }
	return 0;
}

/*
样例输入:
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
样例输出:
case 1: 12
case 2: 9
case 3: 2500050000
*/

  

 

posted @ 2017-02-11 21:31  执蘖执蘖  阅读(124)  评论(0编辑  收藏  举报