1. 程式人生 > >UVA12657 Boxes in a Line:題解

UVA12657 Boxes in a Line:題解

題目連結:https://www.luogu.org/problemnew/show/UVA12657

分析:

此題使用手寫連結串列+模擬即可。(其實可以用list,而且更簡便,但是會大大的超時)

肯定是不能直接用陣列模擬了,因為n,m的大小會達到100000. 然後,
1.可以編寫一些輔助函式來設定連結關係。
2.注意 op==3的時候,要對xy相鄰的情況進行特判,因為有這種情況
2 1 (頭節點)
3 1 2 (尾節點)
3.我們會發現如果反轉兩次,就相當於沒有翻轉。如果翻轉一次,op=1變為op=2;op=2變為op=1;如果翻轉一次,n為奇數時,奇數位置不變,但是n為偶數的時候,奇數變偶數。
(為什麼要用雙向連結串列?因為我們需要知道它左邊和右邊)

程式碼:

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100000+10;
int left[maxn],right[maxn],inv;
void link(int L,int R)
{
	left[R]=L;
	right[L]=R;
} 
long long number(int n)
{
	int x=0;
	long long total=0;
	for(int i=1;i<=n;i++)
	{
		x=right[x];
		if(i%2!=0)total+=
x; } if(inv!=0&&n%2==0)total=(long long)n*(n+1)/2-total; return total; } int main() { int n,m,T=1; 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; inv=0; while(m--) { int order,X,Y; scanf
("%d",&order); if(order==4) { inv=!inv; continue; } scanf("%d %d",&X,&Y); if(order==3&&right[Y]==X)swap(X,Y);//X,Y相鄰要特殊考慮 if(order!=3&&inv)order=3-order; if(order==1&&left[Y]==X)continue; if(order==2&&right[Y]==X)continue; int LX,RX,LY,RY; LX=left[X]; RX=right[X]; LY=left[Y]; RY=right[Y]; if(order==1) { link(X,Y); link(LX,RX); link(LY,X); } else if(order==2) { link(Y,X); link(LX,RX); link(X,RY); } else if(order==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); } } } printf("Case %d: %lld\n",T++,number(n)); } return 0; } 撒花~