BZOJ1106 [POI2007]立方体大作战tet 树状数组

给定玩家一个有2n个元素的栈,元素一个叠一个地放置。这些元素拥有n个不同的编号,每个编号正好有两个
元素。玩家每次可以交换两个相邻的元素。如果在交换之后,两个相邻的元素编号相同,则将他们都从栈中移除,

所有在他们上面的元素都会掉落下来并且可以导致连锁反应。玩家的目标是用最少的步数将方块全部消除。

碰到像1212这样的肯定要交换一次

所以记录一下未消除的数字个数,以及出现过的数字的位置

当每个数第二次出现的时候,答案就增加这两个位置之间剩余数字的个数.

这个用树状数组维护

#include<bits/stdc++.h>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
#define lowbit(x) (x&(-x))
using namespace std;
const int N=200005;
int n,x,c[N],pos[N],cnt,ans;
void change(int x,int v)
{
	while(x<=n){
		c[x]+=v;x+=lowbit(x);
	}
}
int query(int x)
{
	int ret=0;
	while(x>0){
		ret+=c[x];x-=lowbit(x);
	}
	return ret;
} 
int main()
{
	scanf("%d",&n);
	n*=2;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		if(!pos[x]){
			pos[x]=i;cnt++;
			change(pos[x],1);
		}
		else{
			ans+=cnt-query(pos[x]);
			change(pos[x],-1);
			cnt--;
		}
	}
	printf("%d",ans);
	return 0;
}
 


发布了39 篇原创文章 · 获赞 4 · 访问量 5813

猜你喜欢

转载自blog.csdn.net/Wolf_Reiser/article/details/78681071