uva-12657 - Boxes in a Line(双向链表)
12657 - 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 n
from 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
题解:
给你一个从1~n的数,然后给你操作方案
• 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.
用双向链表,用着刘汝佳的模版,却无限wa
我的wa代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<stack> #include<vector> using namespace std; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); #define mem(x,y) memset(x,y,sizeof(x)) #define SI(x) scanf("%d",&x) #define SL(x) scanf("%lld",&x) #define PI(x) printf("%d",x) #define PL(x) printf("%lld",x) #define P_ printf(" "); typedef long long LL; const int MAXN=1e5+100; int lef[MAXN],righ[MAXN]; void link(int l,int r){ lef[r]=l; righ[l]=r; } int main(){ int n,m; int s,x,y,kase=0; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++){ lef[i]=i-1; righ[i]=(i+1)%(n+1); } lef[0]=n;righ[0]=1; int flot=0; while(m--){ scanf("%d",&s); if(s==4){ flot=!flot; continue; } scanf("%d%d",&x,&y); int lx=lef[x],rx=righ[x],ly=lef[y],ry=righ[y]; if(s!=3&&flot)s=3-s; /****************************************/ if(s == 3 && righ[y] == x) swap(x, y); if(s == 1 && x == lef[y]) continue; if(s == 2 && x == righ[y]) continue; /****************************************/ if(s==1){ link(lx,rx);link(ly,x);link(x,y); } else if(s==2){ link(lx,rx);link(y,x);link(x,ry); } else if(s==3){ if(righ[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 cur=0; LL ans=0; for(int i=1;i<=n;i++){ cur=righ[cur]; if(i&1)ans+=cur; } if(flot&&n%2==0)ans=(LL)n*(n+1)/2-ans; printf("Case %d: %lld\n",++kase,ans); } return 0; }
刘汝佳的ac代码:
#include<cstdio> #include<algorithm> using namespace std; const int maxn = 100000 + 5; int n, left[maxn], right[maxn]; inline void link(int L, int R) { right[L] = R; left[R] = L; } int main() { freopen("1.txt","r",stdin); freopen("2.txt","w",stdout); int m, kase = 0; while(scanf("%d%d", &n, &m) == 2) { for(int i = 1; i <= n; i++) { left[i] = i-1; right[i] = (i+1) % (n+1); } right[0] = 1; left[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 && right[Y] == X) swap(X, Y); if(op != 3 && inv) op = 3 - op; if(op == 1 && X == left[Y]) continue; if(op == 2 && X == right[Y]) continue; int LX = left[X], RX = right[X], LY = left[Y], RY = right[Y]; if(op == 1) { link(LX, RX); link(LY, X); link(X, Y); } else if(op == 2) { link(LX, RX); link(Y, X); link(X, RY); } else if(op == 3) { if(right[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 = right[b]; if(i % 2 == 1) ans += b; } if(inv && n % 2 == 0) ans = (long long)n*(n+1)/2 - ans; printf("Case %d: %lld\n", ++kase, ans); } return 0; }
再次比赛,出现了这个题,要注意,当两个数挨着的时候,要特判,否则会造成链表出乱,死循环,ac:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int MAXN = 100100; typedef long long LL; int L[MAXN], R[MAXN]; void link(int l, int r){ R[l] = r; L[r] = l; } int main(){ int n, m; int kase = 0; while(~scanf("%d%d", &n, &m)){ for(int i = 0; i < n; i++){ link(i, i + 1); } L[0] = n; R[n] = 0; int q, x, y; int l, r, ll, rr; int sw = 0; while(m--){ scanf("%d", &q); if(q == 4){ sw ^= 1; } else{ scanf("%d%d", &x, &y); if(q == 1 || q == 2){ if(sw) q = 3 - q; } if(q == 1 && L[y] == x) continue; if(q == 2 && R[y] == x) continue; if(q == 3){ l = L[x]; r = R[x]; ll = L[y]; rr = R[y]; if(R[x] == y){ link(l, y); link(y, x); link(x, rr); } else if(R[y] == x){ link(ll, x); link(x, y); link(y, r); } else{ link(l, y); link(y, r); link(ll, x); link(x, rr); } } else if(q == 2){ l = L[x]; r = R[x]; ll = L[y]; rr = R[y]; link(l, r); link(y, x); link(x, rr); } else if(q == 1){ l = L[x]; r = R[x]; ll = L[y]; rr = R[y]; link(l, r); link(ll, x); link(x, y); } } } LL ans = 0; if(sw){ for(int i = L[0], j = 1; i ; i = L[i], j++){ if(j & 1) ans += i; } } else{ for(int i = R[0], j = 1; i ; i = R[i], j++){ if(j & 1) ans += i; } } printf("Case %d: %lld\n", ++kase, ans); } return 0; }