1. 程式人生 > >[bzoj1106][亂搞]立方體大作戰tet

[bzoj1106][亂搞]立方體大作戰tet

Description

一個叫做立方體大作戰的遊戲風靡整個Byteotia。這個遊戲的規則是相當複雜的,所以我們只介紹他的簡單規 則:給定玩家一個有2n個元素的棧,元素一個疊一個地放置。這些元素擁有n個不同的編號,每個編號正好有兩個 元素。玩家每次可以交換兩個相鄰的元素。如果在交換之後,兩個相鄰的元素編號相同,則將他們都從棧中移除, 所有在他們上面的元素都會掉落下來並且可以導致連鎖反應。玩家的目標是用最少的步數將方塊全部消除。

Input

第一行包含一個正整數n(1<=n<=50000)。接下來2n行每行一個數ai,從上到下描述整個棧,保證每個數出現且 僅只出現兩次(1<=ai<=n)。初始時,沒有兩個相同元素相鄰。並且保證所有資料都能在1000000步以內出解。

Output

第一行包含一個數m,表示最少的步數。

Sample Input

樣例輸入1

5

5

2

3

1

4

1

4

3

5

2

樣例輸入2

3

1

2

3

1

2

3

Sample Output

樣例輸出1

2

樣例輸出2

3

題解

顯然如果兩個數之間沒有兩個相同的數字 這兩個數要消掉,肯定至少要交換他們距離那麼多次 拿一個棧壓一下 消掉兩個數的代價,相當於他們的距離-他們之間能被消掉的數的對數 亂搞就好了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#define LL long long
#define mp(x,y) make_pair(x,y)
using namespace std;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void write(int x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
inline void print(int x){write(x);printf(" ");}
int n,sta[51000],tp;
int pos[51000],s[51000];
int lowbit(int x){return x&-x;}
void change(int x,int c){for(int i=x;i<=n;i+=lowbit(i))s[i]+=c;}
int findsum(int x){int ret=0;for(int i=x;i>=1;i-=lowbit(i))ret+=s[i];return ret;}
int main()
{
	n=read();
	int ans=0;
	for(int i=1;i<=2*n;i++)
	{
		int x=read();
		if(!pos[x])sta[++tp]=x,pos[x]=tp;
		else
		{
			 ans+=tp-pos[x]-findsum(pos[x]);
			 change(1,1);change(pos[x],-1);
		}
	}
	printf("%d\n",ans);
	return 0;
}