移动盒子(Boxes in a line,UVa 12657)
双向链表
1.不一定真的需要实现整条链表的逆转,而是先用flag标记
2.逆转时op<3需op=3-op达到逆转后效果
3.op=3时有两种情况:①x,y相邻-->统一让y的左边是x(改变它们的指向的数字,x,y只是一个代号)
②x,y不相邻
4.偶链逆转在奇位变偶,偶位变奇;奇链不受影响
双向链表函数:
void link(int L,int R)
{
right[L]=R;
left[R]=L;
}
就测试数据及其推算而言,这种双向链表的方式不需要注意语句的顺序,即使用时不存在顺序不一样链表丢失的情况
测试数据:
6 4
1 1 4
2 3 5
3 1 6
4
100000 1
4
代码如下:
#include<bits/stdc++.h>
int right[10000000],left[10000000],flag=0;
void link(int L,int R)
{
right[L]=R;
left[R]=L;
}
int main()
{
int n,m,i;
scanf("%d %d", &n, &m);
for(i=1;i<=n;i++)
{
left[i]=i-1;
right[i]=(i+1)%(n+1);
}
left[0]=n;
right[0]=1;
for(i=1;i<=m;i++)
{
int op,x,y;
scanf("%d", &op);
if(op==4)
flag=!flag;
else
{
scanf("%d %d",&x,&y);
if(op==3&&right[y]==x)
std::swap(x,y);
if(op!=3&&flag)
op=3-op;
if(op==1&&left[y]==x) continue;
if(op==2&&right[y]==x)continue;
int lx=left[x],rx=right[x],ly=left[y],ry=right[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(left[y]==x)
{link(lx,y);link(y,x);link(x,ly);}
else
{link(lx,y);link(y,rx);link(ly,x);link(x,ry);}
}
}
}
long long ans=0;
int b=0;
for(i=1;i<=n;i++)
{
b=right[b];
if(i%2==1)
ans+=b;
}
if(n%2==0&&flag) ans=(long long)n*(n+1)/2-ans;
printf("%lld",ans);
return 0;
}