1. 程式人生 > >UVA - 12657(雙向連結串列,左插入,右插入,交換,翻轉)

UVA - 12657(雙向連結串列,左插入,右插入,交換,翻轉)

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; }