一个叫做立方体大作战的游戏风靡整个Byteotia。这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置。这些元素拥有n个不同的编号,每个编号正好有两个元素。玩家每次可以交换两个相邻的元素。如果在交换之后,两个相邻的元素编号相同,则将他们都从栈中移除,所有在他们上面的元素都会掉落下来并且可以导致连锁反应。玩家的目标是用最少的步数将方块全部消除。
一个叫做立方体大作战的游戏风靡整个Byteotia。这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置。这些元素拥有n个不同的编号,每个编号正好有两个元素。玩家每次可以交换两个相邻的元素。如果在交换之后,两个相邻的元素编号相同,则将他们都从栈中移除,所有在他们上面的元素都会掉落下来并且可以导致连锁反应。玩家的目标是用最少的步数将方块全部消除。
第一行包含一个正整数n(1<=n<=50000)。接下来2n行每行一个数ai,从上到下描述整个栈,保证每个数出现且仅只出现两次(1<=ai<=n)。初始时,没有两个相同元素相邻。并且保证所有数据都能在1000000步以内出解。
第一行包含一个数m,表示最少的步数。
知道思路这题是非常好写的
思路:
贪心,遍历每个数,如果这个数字已经出现过了,答案加上这两个数之间其它数字的个数
并将这个数字从数列中删去就行了
例如:
1 2 3 2 3 1
当遍历到第4个数'2'时,中间有个3,ans++
当遍历到第5个数'3'时,中间没有数字(有个2但已经被删了)
当遍历到第6个数'1'时,中间也没有数字(2和3都被删了)
所以最后答案是1
上面的步骤同时也是证明:删除任意一对数时,一定要保证中间已经没有相同的数字了才是最优解
过程可以用树状数组维护
#include
#define LL long long
int n, flag[50005], tre[100005];
void Update(int k, int x)
{
while(k<=n*2)
{
tre[k] += x;
k += k&-k;
}
}
int Query(int k)
{
int ans = 0;
while(k)
{
ans += tre[k];
k -= k&-k;
}
return ans;
}
int main(void)
{
LL ans;
int i, x;
scanf("%d", &n);
ans = 0;
for(i=1;i<=2*n;i++)
{
scanf("%d", &x);
if(flag[x]==0)
{
Update(i, 1);
flag[x] = i;
}
else
{
ans += Query(i)-Query(flag[x]);
Update(flag[x], -1);
}
}
printf("%lld\n", ans);
return 0;
}
/*
3
1 2 3 2 3 1
*/