崆若的水题之--盒子的鬼畜移动
#include<iostream> using namespace std; const int MAXN=100010; int i,m,n,ileft[MAXN],iright[MAXN]; void link(int L,int R) //将节点L和R连接起来,L在左,R在右 { iright[L]=R; ileft[R]=L; } int main() { scanf("%d%d",&n,&m); //建立双向循环链表,链表中有n+1个节点:0,1,……,n for(i=1;i<n;i++) { ileft[i]=i-1; iright[i]=i+1; } iright[0]=1;ileft[0]=n; iright[n]=0;ileft[n]=n-1; //------ int op,X,Y,flag=0; //链表方向标志 while(m--) { scanf("%d",&op); if(op==4) flag=!flag; else { scanf("%d%d",&X,&Y); if(op==3 && iright[Y]==X) swap(X,Y); if(op!=3 && flag) op=3-op; //flag为真说明链表方向和最初相反 if(op==1 && X==ileft[Y]) continue; //X已经在Y的左边就忽略 if(op==2 && X==iright[Y])continue; //X已经在Y的右边就忽略 int LX=ileft[X],RX=iright[X],LY=ileft[Y],RY=iright[Y]; if(op==1) { link(LX,RX); link(LY,X); link(X,Y); } if(op==2) { link(LX,RX); link(Y,X); link(X,RY); } if(op==3) { if(iright[X]==Y) { link(LX,Y); link(Y,X); link(X,RY); } else { link(LX,Y); link(Y,RX); link(LY,X); link(X,RY); } } } } long long ans=0; m=0; for(i=1;i<=n;i++) //如果出现偶数个操作4,还是原来的方向 { m=iright[m]; if(i&1) ans+=m; } if(flag && n%2==0) ans=(long long)n*(n+1)/2-ans; cout<<ans; //system("pause"); return 0; }
试题描述
|
你有一行盒子,从左到右依次编号为1,2,3,……,n。可以执行一下四种指令: |
输入
|
第一行包括两个正整数n和m,分别表示盒子个数和指令条数,接下来的m行,每行一条指令,如果是指令1、2或者3时,三部分间有一个空格分隔,如指令1 2 4表示将盒子2移动到盒子4的左边。
|
输出
|
一个正整数,表示所有奇数位置上盒子编号的数字之和。
|
输入示例
|
6 4
1 1 4 2 3 5 3 1 6 4 |
输出示例
|
12
|
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。