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 1000000000
24 
25 #define maxn 100000+1000
26 
27 #define maxm 500+100
28 
29 #define eps 1e-10
30 
31 #define ll long long
32 
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
",ans); 
91 
92     return 0;
93 
94 }
View Code
原文地址:https://www.cnblogs.com/zyfzyf/p/3968900.html