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 4
kinds 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 executing
2 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 41 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: 12Case 2: 9
Case 3: 2500050000
題意 開始有n個盒子按1到n的順序排列 對這些盒子進行m次操作 每次爲把x移到y的左邊 右邊 交換x,y 顛倒順序中的一個
求操作完成後所有奇數位原盒子序號的和;
直接模擬肯定會超時 用stl中的鏈表也超時 只能用數組自己模擬一個雙向鏈表了 le[i],ri[i]分別表示第i個盒子左邊盒子的序號和右邊盒子的序號 代碼中有註釋
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100005;
int le[N], ri[N], n, m;
typedef long long ll;
void link (int l, int r) //連接l和r,l在左邊
{
le[r] = l; ri[l] = r;
}
int main()
{
int cas = 0, op, x, y, t;
while (scanf ("%d%d", &n, &m) != EOF)
{
for (int i = 1; i <= n; ++i)
ri[i] = i + 1, le[i] = i - 1;
ri[n] = 0, le[0] = n, ri[0] = 1;
int flag = 0; //判斷是否翻轉
while (m--)
{
scanf ("%d", &op);
if (op == 4) flag = !flag;
else
{
scanf ("%d%d", &x, &y);
if (flag && op != 3) op = 3 - op; //翻轉後移動操作就相反了
if (ri[y] == x && op == 3) //方便後面判斷交換是否相鄰
t = x, x = y, y = t;
if ( (op == 1 && le[y] == x) || (op == 2 && ri[y] == x)) continue;
if (op == 1) //x移到y右邊
link (le[x], ri[x]), link (le[y], x), link (x, y);
else if (op == 2) //x移到y左邊
link (le[x], ri[x]), link (x, ri[y]), link (y, x);
else if (y == ri[x]) //op==3&&x,y相鄰
link (le[x], y), link (x, ri[y]), link (y, x);
else //不相鄰
{
int ry = ri[y], ly = le[y];
link (le[x], y), link (y, ri[x]), link (ly, x), link (x, ry);
}
}
}
t = 0; ll ans = 0;
for (int i = 1; i <= n; ++i)
{
t = ri[t];
if (i % 2) ans += t;
}
if (n % 2 == 0 && flag) //n爲偶數且翻轉過 故求的恰爲偶數位的和
ans = (ll) n / 2 * (1 + n) - ans;
printf ("Case %d: %lld\n", ++cas, ans);
}
return 0;
}