UVA - 12657(雙向連結串列,左插入,右插入,交換,翻轉)
阿新 • • 發佈:2018-11-21
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;
}