1. 程式人生 > >Uva 12657 移動盒子(雙向鏈表)

Uva 12657 移動盒子(雙向鏈表)

can swap i++ 來看 ont 第一個 編號 bit wap

題意:

你有一行盒子,從左到右依次編號為1, 2, 3,…, n。可以執行以下4種指令:
1 X Y表示把盒子X移動到盒子Y左邊(如果X已經在Y的左邊則忽略此指令)。
2 X Y表示把盒子X移動到盒子Y右邊(如果X已經在Y的右邊則忽略此指令)。
3 X Y表示交換盒子X和Y的位置。
4 表示反轉整條鏈。

分析:

從操作1,2來看, 需要有一個數據結構, 記錄每個盒子左邊和右邊是什麽。

操作4如果真的模擬復雜度較高也比較麻煩, 可以考慮建一個標記, 表示有沒執行過操作4

但是註意了 如果執行了操作4後, 如果操作1 2操作不變的話, 那麽操作1就是2,2 就是1(放在左邊 + 反轉 = 放在右邊)

雙向鏈表有一個比較實用的函數

技術分享

意思就是將L,R兩個元素相連, L在R的左邊, R在L的右邊。

 1 #include <bits/stdc++.h>
 2 const int maxn =  100000 + 7;
 3 int n, left[maxn], right[maxn];
 4 void link(int L, int R){//第一個參數是 L,第二個是R,
 5     right[L] = R;
 6     left[R] = L;
 7 }
 8 int main()
 9 {
10     int m, kase = 0;
11     while(scanf("%d %d", &n, &m) == 2
){ 12 for(int i = 1; i <= n; i++){ 13 left[i] = i -1; 14 right[i] = (i+1) % (n+1); 15 } 16 right[0] = 1;//註意0右邊是1 左邊是 n 17 left[0] = n; 18 int op, X, Y, inv = 0; 19 while(m--){ 20 scanf("%d", &op); 21 if(op == 4
) inv = !inv; 22 else { 23 scanf("%d%d",&X, &Y); 24 if(op == 3 && right[Y] == X) 25 std::swap(X,Y); 26 if(op != 3 && inv) op = 3 - op; 27 if(op == 1 && X == left[Y]) continue; 28 if(op == 2 && X == right[Y]) continue; 29 30 int LX = left[X], RX = right[X], LY = left[Y], RY = right[Y]; 31 if(op == 1){ 32 link(LX,RX); link(LY,X); link(X,Y); 33 } 34 else if(op == 2){ 35 link(LX,RX); link(Y,X); link(X,RY); 36 } 37 else if(op == 3){ 38 if(right[X] == Y){ 39 link(LX,Y); link(Y,X); 40 link(X,RY); 41 } 42 else { 43 link(LX,Y); 44 link(Y,RX); 45 link(LY,X); 46 link(X,RY); 47 } 48 } 49 } 50 } 51 int b = 0; 52 long long ans = 0; 53 for(int i = 1; i <= n; i++){ 54 b = right[b]; 55 if(i % 2 == 1) ans += b; 56 } 57 if(inv && n % 2 == 0) ans = (long long) n * (n+1)/2 - ans; 58 printf("Case %d: %lld\n", ++kase, ans); 59 } 60 }

Uva 12657 移動盒子(雙向鏈表)