[POI2007]立方体大作战tet
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 821 Solved: 601
[Submit][Status][Discuss]
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
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
2
样例输出2
3
HINT
Source
题解:其实就是暴力吧,如果直接暴力复杂度不对,所以用树状数组优化
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstring> 7 8 #define N 100007 9 using namespace std; 10 inline int read() 11 { 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 int n,ans; 18 int a[N],t[N]; 19 int l[N]; 20 int query(int x) 21 { 22 int sum=0; 23 for(int i=x;i;i-=i&(-i)) 24 sum+=t[i]; 25 return sum; 26 } 27 void add(int x,int val) 28 { 29 for(int i=x;i<=2*n;i+=i&(-i)) 30 t[i]+=val; 31 } 32 int main() 33 { 34 n=read(); 35 for(int i=1;i<=2*n;i++) 36 a[i]=read(); 37 for(int i=1;i<=2*n;i++) 38 if(!l[a[i]])add(i,1),l[a[i]]=i; 39 else 40 { 41 ans+=query(i)-query(l[a[i]]); 42 add(l[a[i]],-1); 43 } 44 printf("%d",ans); 45 }