連結串列-雙向連結串列&&UVa12657 Boxes in a Line(移動盒子)的理解與解析
連結串列-雙向連結串列&&UVa12657 Boxes in a Line(移動盒子)的理解與解析
You have n boxes in a line on the table numbered 1 . . . n from left to right. Your task is to simulate 4kinds of commands:
• 1 X Y : move box X to the left to Y (ignore this if X is already the left of Y )
• 2 X Y : move box X to the right to Y (ignore this if X is already the right of Y )
• 3 X Y : swap box X and Y
• 4: reverse the whole line.
Commands are guaranteed to be valid, i.e. X will be not equal to Y .For example, if n = 6, after executing 1 1 4, the line becomes 2 3 1 4 5 6. Then after executing2 3 5, the line becomes 2 1 4 5 3 6. Then after executing 3 1 6, the line becomes 2 6 4 5 3 1.Then after executing 4, then line becomes 1 3 5 4 6 2
Input
There will be at most 10 test cases. Each test case begins with a line containing 2 integers n, m(1 ≤ n, m ≤ 100, 000). Each of the following m lines contain a command.
Output
For each test case, print the sum of numbers at odd-indexed positions. Positions are numbered 1 to nfrom left to right.
Sample Input
6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4
Sample Output
Case 1: 12
Case 2: 9
Case 3: 2500050000
Solution
解決方法來自書上
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=100000+5;
int n,leftt[maxn],rightt[maxn];//left and right is ambiguous
void link(int L,int R)
{
rightt[L]=R;leftt[R]=L;
}
int main()
{
int m,kase=0;
while(scanf("%d%d",&n,&m)==2){
for(int i=1;i<=n;i++){
leftt[i]=i-1;
rightt[i]=(i+1)%(n+1);
}
rightt[0]=1;leftt[0]=n;
int op,X,Y,inv=0;
while(m--){
scanf("%d",&op);
if(op==4) inv=!inv;
else{
scanf("%d%d",&X,&Y);
if(op==3&&rightt[Y]==X) swap(X,Y);//!為了轉化為同一種情況來處理,x、y只是一個代號,反正結果變得是值
if(op!=3&&inv) op=3-op;
if(op==1&&X==leftt[Y]) continue;
if(op==2&&X==rightt[Y]) continue;
int LX=leftt[X],RX=rightt[X],LY=leftt[Y],RY=rightt[Y];
//下面分類討論,不要漏掉
if(op==1){
link(LX,RX);link(LY,X);link(X,Y);
}//X的左右連起來,X和Y左,X和Y
else if(op==2){
link(LX,RX);link(Y,X);link(X,RY);
}//X的左右連起來,Y和X,X和Y右 按照鏈的順序來寫,可能思路更清晰
else if(op==3){
if(rightt[X]==Y) {link(LX,Y);link(Y,X);link(X,RY);}
else {link(LX,Y);link(Y,RX);link(LY,X);link(X,RY);}
}
}
}
int b=0;
long long ans=0;
for(int i=1;i<=n;i++){
b=rightt[b];//向右推移
if(i%2==1) ans+=b;
}
if(inv&&n%2==0) ans=(long long)n*(n+1)/2-ans;//如果n不是偶數的話,倒一下結果也一樣
printf("Case %d: %lld\n",++kase,ans);
}
return 0;
}
謝謝