【bzoj4994】[Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组

题目描述

给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数

样例输入

4
3
2
4
4
1
3
2
1

样例输出

3


题解

树状数组

WH说是CDQ分治直接把我整蒙了。。。

把所有数按照第一次出现位置从小到大排序,然后扫一遍。此时一定是满足$a_j>a_i$的。

那么只需要求出$(a_j,b_j)$中以前出现过的$b_i$的数目。使用树状数组维护即可。

时间复杂度$O(n\log n)$

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 50010
using namespace std;
struct data
{
	int a , b;
	bool operator<(const data &x)const {return a < x.a;}
}v[N];
int n , f[N << 1];
inline void add(int x)
{
	int i;
	for(i = x ; i <= n << 1 ; i += i & -i) f[i] ++ ;
}
inline int query(int x)
{
	int i , ans = 0;
	for(i = x ; i ; i -= i & -i) ans += f[i];
	return ans;
}
int main()
{
	int i , x , ans = 0;
	scanf("%d" , &n);
	for(i = 1 ; i <= n << 1 ; i ++ )
	{
		scanf("%d" , &x);
		if(!v[x].a) v[x].a = i;
		else v[x].b = i;
	}
	sort(v + 1 , v + n + 1);
	for(i = 1 ; i <= n ; i ++ ) ans += query(v[i].b - 1) - query(v[i].a - 1) , add(v[i].b);
	printf("%d\n" , ans);
	return 0;
}

 

 

posted @ 2017-09-27 08:45  GXZlegend  阅读(313)  评论(0编辑  收藏  举报