uva12657(雙向鏈表

題目大意:
給你N個盒子,分別標號爲1~N;有下面4種操作:

“1 X Y” 表示將X移到Y的左邊;

“2 X Y” 表示將Y移到Y的右邊;

“3 X Y” 表示交換X與Y的位置;

“4” 表示將1~N所有的盒子反序。

要你求經過M次操作之後,所有奇數位置的盒子標號之和。

解題思路
大體的說一下 代碼裏有詳細註釋
當n是奇數時,操作4逆序不會影響奇數位置盒子標號之和
當n是偶數時,操作4逆序就會影響 最終結果是所有位置標號之和-奇數位置標號之和
一開始對那個swap(x,y)一直不理解
然後慢慢捋一捋 3 x,y 是交換 x,y的位置 如果當時位置是 y,x的話 就把x,y的序號互換,這樣就是把 操作轉化爲交換 y,x的位置 如果本來就是 x,y的話 就是交換xy的位置

代碼如下

#include<iostream>
using namespace std;
const int maxn=1e5+10;
int l[maxn],r[maxn];
void link(int a,int b)//讓a,b挨着 
{
	r[a]=b;
	l[b]=a;
}
int main()
{
	int n,m,x,y,flag;
	int k;
	int cas=0;
	int i;
	while(cin>>n>>m)
	{
		flag=0;//判斷是否翻轉 
		for(i=1;i<=n;i++)
		{
			r[i]=(i+1);
			l[i]=i-1;
		}
		r[0]=1;
		l[0]=n;
		while(m--)
		{
			cin>>k;
			if(k==4)
			  flag=!flag;
			else
			{
				cin>>x>>y;
				if(k==3&&r[y]==x)
				   swap(x,y);//方便後面統一判斷相鄰不相鄰 
				if(k!=3&&flag)//翻轉後所以操作動作都相反 
				   k=3-k;
				if(k==1&&l[y]==x)
				   continue;
				if(k==2&&r[y]==x)
				   continue;
				int lx=l[x],rx=r[x],ly=l[y],ry=r[y];
				if(k==1)//x移到y左邊 
				{
					link(lx,rx);//原來x左邊的和原來x右邊的挨着 
					link(ly,x);//原來y左邊的和x挨着 
					link(x,y);//x和y挨着 
				}
				else if(k==2)//x移到y右邊 
				{
					link(lx,rx);//原來x左邊的和原來x右邊的挨着 
					link(y,x);//y和x挨着 
					link(x,ry);//x和原來y的右邊的挨着 
				}
				else{//交換x y的位置 
					if(r[x]==y)//x y相鄰 的話 
					{
						link(lx,y);//原來x的左邊和y挨着 
						link(y,x);//y 和 x挨着 
						link(x,ry);//x和原來y的右邊挨着 
					}
					else//不相鄰的話 
					{
						link(lx,y);// 原來x的左邊和y挨着 
						link(y,rx);//y和原來x的右邊挨着 
						link(ly,x);//原來y的左邊和x挨着 
						link(x,ry);//x和原來y的右邊挨着 
					}
				}
			}
		}
		long long ans=0,num=0;
		int kk=0;
		for(i=1;i<=n;i++)
		{
			kk=r[kk];
			num+=kk;
			if(i%2)
			  ans+=(kk); 
		}
		if(n%2==0&&flag==1)
		  ans=num-ans;
		cas++;
		cout<<"Case "<<cas<<": ";
		cout<<ans<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章