首页 > 代码库 > BZOJ1106: [POI2007]立方体大作战tet

BZOJ1106: [POI2007]立方体大作战tet

1106: [POI2007]立方体大作战tet

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 419  Solved: 302
[Submit][Status]

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

HINT

Source

题解:

又被坑了。。。

一直在想有什么算法能够根据数据来确定先换谁,在换谁。。。思路完全不对啊。。。

直接贪心的去换离得最近的木块即可

别人的题解:

首先如果对于两个相同数字的方块,如果他们之间还有可以配对的两个方块,显然先消掉中间的方块更优。

但是如果他们之间有k个无法配对的方块,我们就至少需 要k次交换消掉现在的这两块。我们就可以统计一下每两个相同的方块之间有多少无法配对的方块。可以用一个树状数组来维护……

orz。。。

代码:

 1 #include<cstdio> 2  3 #include<cstdlib> 4  5 #include<cmath> 6  7 #include<cstring> 8  9 #include<algorithm>10 11 #include<iostream>12 13 #include<vector>14 15 #include<map>16 17 #include<set>18 19 #include<queue>20 21 #include<string>22 23 #define inf 100000000024 25 #define maxn 100000+100026 27 #define maxm 500+10028 29 #define eps 1e-1030 31 #define ll long long32 33 #define pa pair<int,int>34 35 #define for0(i,n) for(int i=0;i<=(n);i++)36 37 #define for1(i,n) for(int i=1;i<=(n);i++)38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)42 43 using namespace std;44 45 inline int read()46 47 {48 49     int x=0,f=1;char ch=getchar();50 51     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}52 53     while(ch>=0&&ch<=9){x=10*x+ch-0;ch=getchar();}54 55     return x*f;56 57 }58 int n,v[maxn],s[maxn];59 inline void add(int x,int y)60 {61     for(;x<=2*n;x+=x&(-x))s[x]+=y;62 }63 inline int sum(int x)64 {65     int t=0;66     for(;x;x-=x&(-x))t+=s[x];67     return t;68 }69 70 int main()71 72 {73 74     freopen("input.txt","r",stdin);75 76     freopen("output.txt","w",stdout);77 78     n=read();79     int ans=0;80     for1(i,2*n)81      {82         int x=read();83         if(!v[x]){v[x]=i;add(i,1);}84         else 85         {86             ans+=sum(i)-sum(v[x]-1)-1;87             add(v[x],-1);88         }89      }    90     printf("%d\n",ans); 91 92     return 0;93 94 }
View Code

 

 

BZOJ1106: [POI2007]立方体大作战tet