/*
这道题是刘汝佳紫书144页的题目,题意不再赘述,主要记录一下这道题的收获。
由于插入的位置时左时右,因此单向链表不能处理这类问题,需要使用双向链表。
反转操作不一定真的要反转,应该根据情况灵活应对。
另外就是链表的不可忽视的一个特点,那就是链表中节点的编号不是该节点在链表中位置的编号,节点编号与节点
当中的内容是一开始就对应好不变的。比如现在要把4号球挪到6号球的左边,不需要遍历链表找到哪个节点的数字
是4,因为一开始就决定了4号球对应的节点编号是4
*/
#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-8;
const int maxn = 1e5 + 5;
int l[maxn],r[maxn];
void addlink(int L ,int R)
{
r[L] = R; l[R] = L;
}
void init(int n)
{
mem(l , 0);
mem(r,0);
for(int i = 1;i <= n;i++){
addlink(i-1,i);
}
addlink(n , 0);
return ;
}
int main()
{
int n , m , op , inv , kase = 0 ;
while(scanf("%d %d",&n,&m)!=EOF){
init(n);
inv = 0;
int x , y;
for(int i = 1;i<=m;i++){
scanf("%d",&op);
if(inv&&op==1) op = 2;
else if(inv&&op==2) op = 1;
if(op==4) inv ^= 1;
else{
scanf("%d %d",&x,&y);
int lx = l[x], rx = r[x];
int ly = l[y] , ry = r[y];
if(op == 1){
if(ly == x) continue;
addlink(lx , rx);
addlink(ly , x);
addlink(x , y);
}
else if(op==2){
if(ry == x) continue;
addlink(lx , rx);
addlink(x , ry);
addlink(y , x);
}
else if(op == 3){
if(ly == x ){ //一开始这里的特判没注意T了多次,即交换两球位置的时候要特判两球是否是相邻的
addlink(y,x);
addlink(lx,y);
addlink(x,ry);
}
else if(lx == y){
addlink(x,y);
addlink(ly,x);
addlink(y,rx);
}
else{
addlink(ly , x);
addlink(x , ry);
addlink(lx , y);
addlink(y , rx);
}
}
}
}
LL sum = 0;
int time = 0;
if(!inv){
for(int i = r[0] ; i != 0 ; i = r[i] ){
++time;
if(time%2)
sum += i;
}
}
else{
for(int i = l[0];i!=0;i = l[i]){
++time;
if(time%2)
sum += i;
}
}
printf("Case %d: %lld\n",++kase , sum);
}
return 0;
}
Uva12657 Boxes in a line
最新推荐文章于 2023-01-02 14:06:09 发布