[Usaco2017 Feb]Why Did the Cow Cross the Road III (Gold)

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

Sample Input
4
3
2
4
4
1
3
2
1

Sample Output
3

HINT
N<=100000


树状数组维护,一个数出现第一次就加入树状数组,出现第二次的时候统计有多少个数出现一次,并把当前数去掉。记得倒着加入

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) ((x)&(-x))
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
	int x=0,f=1;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x>=10)     print(x/10);
	putchar(x%10+'0');
}
const int N=2e5;
int tree[N+10],vis[N+10];
int n,ans;
void insert(int x,int v){for (;x<=n;x+=lowbit(x))	tree[x]+=v;}
int query(int x){
	int res=0;
	for (;x;x-=lowbit(x))	res+=tree[x];
	return res;
}
int main(){
	n=read()*2;
	for (int i=1,x;i<=n;i++){
		x=read();
		if (vis[x]){
			insert(vis[x],-1);
			ans+=query(vis[x]);
		}
		else	vis[x]=n-i+1,insert(vis[x],1);    //倒着加入
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Wolfycz/p/8414389.html