UVA12657 Boxes in a Line:題解
阿新 • • 發佈:2018-12-10
題目連結: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;
}
撒花~