版权声明:转载请在原文附上源连接以及作者,谢谢~ https://blog.csdn.net/weixin_39778570/article/details/83691978
Boxes in a Line
ACM汇总学习:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目:https://vjudge.net/problem/UVA-12657
题目:模拟链表4中操作,x左插入y,x右插入y,x交换y,翻转链表,计算链表中奇数位置的和
解法:使用两个数组模拟双向链表,翻转操作不用真的翻转,记录翻转次数就好,奇数次则反向计算,注意!当链表被翻转过了的时候,x左插入y变为x右插入y,x右插入y边成x左插入y
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int maxn = 1e5+10;
template <class T>inline bool sf(T &ret){
char c; int sgn;
if(c=getchar(),c==EOF)return 0;
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0');
ret*=sgn;
return ret;
}
struct DList{
int Left[maxn],Right[maxn];
int head = 0, tail, inv = 0;
void init(int n){
// memset(Left,0,sizeof(int)*(n+3));
// memset(Right,0,sizeof(int)*(n+3));
inv = 0;
head = 0;
tail = n+1;
Right[head] = 1;
fo(i,1,n){
Left[i] = i-1;
Right[i] = i+1;
}
Left[tail] = n;
// fo(i,1,n+1)cout<<Left[i]<<" ";
// putchar(10);
// fo(i,1,n+1)cout<<Right[i]<<" ";
}
void link(int x, int y){ // x连接y
Right[x] = y; Left[y] = x;
}
void XLeftY(int x, int y){ // x左插y
if(x==Left[y]){
return;
}else if(x==Right[y]){
link(Left[y],x);
link(y,Right[x]);
link(x,y);
}else{
link(Left[x],Right[x]);
link(Left[y],x);
link(x,y);
}
}
void XRightY(int x, int y){ // x右插y
if(Right[x]==y){
link(Left[x],y);
link(x,Right[y]);
link(y,x);
}else if(x==Right[y]){
return;
}else{
link(Left[x],Right[x]);
link(x,Right[y]);
link(y,x);
}
}
void XSwapY(int x, int y){ // 交换位置
if(Right[x]==y){
link(Left[x],y);
link(x,Right[y]);
link(y,x);
}else if(Left[x]==y){
link(Left[y],x);
link(y,Right[x]);
link(x,y);
}else{
int Lx = Left[x], Rx = Right[x];
int Ly = Left[y], Ry = Right[y];
link(Lx,y);link(y,Rx);link(Ly,x);link(x,Ry);
}
}
void Inv(){ // 链表逆转
inv ^= 1;
}
// odd-sum
ll sum(){
ll ans = 0;
if(inv){
int cnt = 1;
for(int i=Left[tail]; i; i=Left[i]){
if(cnt&1) ans += i;
cnt^=1;
}
}else{
int cnt = 1;
for(int i=Right[head]; i!=tail; i=Right[i]){
if(cnt&1) ans += i;
cnt^=1;
}
}
return ans;
}
void PF(){
int cnt = 1;
for(int i=Right[head]; i!=tail; i=Right[i]){
cout<<i<<" ";
cnt++;
}
putchar(10);
for(int i=Left[tail]; i; i=Left[i]){
cout<<i<<" ";
cnt++;
}
putchar(10);
}
}L;
int n,m;
int main(){
int kase=0;
while(scanf("%d%d",&n,&m)==2){
L.init(n);
int op,x,y;
fo(i,1,m){
// L.PF();
sf(op);
if(op==4){
L.Inv();
continue;
}
sf(x),sf(y);
if(L.inv&&op!=3)op = 3-op; // 逆转过的插入操作要修改,插在左边即插在原串右边
if(op==1){
L.XLeftY(x,y);
}else if(op==2){
L.XRightY(x,y);
}else if(op==3){
L.XSwapY(x,y);
}
}
ll ans = L.sum();
printf("Case %d: %lld\n",++kase,ans);
}
return 0;
}