[BZOJ 1106] [POI2007] 立方体大作战tet 【树状数组】

题目链接:BZOJ - 1106

题目分析

从1到2n枚举每一个位置。

如果枚举到某一个数,这个数已经是第二次出现,那么就看它和第一次出现的位置之间有多少数还没有被匹配,有多少没有匹配的就要进行多少次交换。

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int MaxN = 100000 + 5;

int n, Ans;
int A[MaxN], T[MaxN], L[MaxN];

void Add(int x, int Num)
{
	for (int i = x; i <= n; i += i & -i)
		T[i] += Num;
}

int Get(int x)
{
	int ret = 0;
	for (int i = x; i; i -= i & -i)
		ret += T[i];
	return ret;
}

int main()
{
	scanf("%d", &n);
	n <<= 1;
	for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);
	Ans = 0;
	for (int i = 1; i <= n; ++i)
	{
		if (L[A[i]] == 0)
		{
			L[A[i]] = i;
			Add(i, 1);
		}
		else
		{
			Ans += Get(i) - Get(L[A[i]]);
			Add(L[A[i]], -1);
		}
	}
	printf("%d\n", Ans);
	return 0;
}

  

时间: 2024-12-28 09:26:16

[BZOJ 1106] [POI2007] 立方体大作战tet 【树状数组】的相关文章

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

1106: [POI2007]立方体大作战tet Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 682  Solved: 496[Submit][Status][Discuss] Description 一个叫做立方体大作战的游戏风靡整个Byteotia.这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置.这些元素拥有n个不同的编号,每个编号正好有两个元素.玩家每次可以交换两个相邻的元素.如

BZOJ 1106 [POI2007]立方体大作战tet(树状数组)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1106 [题目大意] 给定玩家一个有2n个元素的栈,元素一个叠一个地放置. 这些元素拥有n个不同的编号,每个编号正好有两个元素. 玩家每次可以交换两个相邻的元素.如果在交换之后,两个相邻的元素编号相同, 则将他们都从栈中移除,所有在他们上面的元素都会掉落下来并且可以导致连锁反应. 玩家的目标是用最少的步数将方块全部消除. [题解] 我们发现如果有一对可消除的方块在另一对中间,那么肯定是

BZOJ 1106 POI2007 立方体大作战tet 模拟

题目大意:给定一个长度为2n的序列,1~n各出现两次,可以交换相邻两项,两个同样的数放在一起会对消,求把所有数对消的最小交换次数 如果有一对在另一对中间 那么这一对肯定要先于另一对交换 除掉这个因素之外答案是确定的 由于保证交换次数<=100W,因此可以从左向右扫,维护一个栈,按顺序记录还没有被消掉的元素 如果新来的元素在栈里出现过,就直接去栈中查找,删除后直接维护就可以了 #include <cstdio> #include <cstring> #include <i

【BZOJ 1106】 [POI2007]立方体大作战tet

1106: [POI2007]立方体大作战tet Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 465  Solved: 336 [Submit][Status] Description 一个叫做立方体大作战的游戏风靡整个Byteotia.这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置.这些元素拥有n个不同的编号,每个编号正好有两个元素.玩家每次可以交换两个相邻的元素.如果在交换之后,

bzoj1106([POI2007]立方体大作战tet)(树状数组)

传送门 首先要看出,对于每一对,其凑到一起所需要的操作次数是中间没被匹配的个数. 于是想到贪心,每次操作所需次数最小的. 但其实做法并不需要这么麻烦,只用从左到右扫一遍. 如果当前数字已经出现过,就统计其中未匹配的个数,同时把这一对标记为“已匹配”,就不会对后面的答案造成影响. 用树状数组维护即可,第一次出现树状数组中对应位置的权值+1,第二次出现时,累计答案,同时把前面相同的数的位置树状数组里权值-1. #include<bits/stdc++.h> #define LL long long

bzoj1106 [POI2007]立方体大作战tet

Description 一个叫做立方体大作战的游戏风靡整个Byteotia.这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置.这些元素拥有n个不同的编号,每个编号正好有两个元素.玩家每次可以交换两个相邻的元素.如果在交换之后,两个相邻的元素编号相同,则将他们都从栈中移除,所有在他们上面的元素都会掉落下来并且可以导致连锁反应.玩家的目标是用最少的步数将方块全部消除. Input 输入文件第一行包含一个正整数n(1<=n<=50000).接

BZOJ 1452: [JSOI2009]Count (二维树状数组)

Description Input Output Sample Input Sample Output 1 2 HINT 二维树状数组的简单应用,c数组的第一维坐标相当于哈希.如果是修改操作,修改前 将当前的值的个数以及祖先都减1, 修改后将个数加1. #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include

【BZOJ】1012: [JSOI2008]最大数maxnumber(树状数组+区间最值)

http://www.lydsy.com/JudgeOnline/problem.php?id=1012 树状数组原来我只懂得sum和add的操作,今天才知道可以有求区间最值的操作,我学习了一下写了个,1a了. 区间最值其实和区间求和差不多,就是将sum数组的含义转移到max,然后通过特定的区间更新max. 在区间求和中,当我们维护max[i]的时候,要找到它前面所有的max[j]来更新,在这里因为是树状数组,所以可以降成一个log级,画图可知,max[i]需要的max只有max[i-2^0],

bzoj 1818 [CQOI 2010] 内部白点 - 扫描线 - 树状数组

题目传送门 快速的列车 慢速的列车 题目大意 一个无限大的方格图内有$n$个黑点.问有多少个位置上下左右至少有一个黑点或本来是黑点. 扫描线是显然的. 考虑一下横着的线段,取它两个端点,横坐标小的地方放一个+1,大的地方放一个-1事件. 然后扫描,扫到的横着的线段更新,竖着的线段用树状数组求答案. 然后考虑这一列上原来存在的黑点有没有被统计,如果没有就加上. Code 1 /** 2 * bzoj 3 * Problem#1818 4 * Accepted 5 * Time: 1824ms 6