1. 程式人生 > >BZOJ4994 [Usaco2017 Feb]Why Did the Cow Cross the Road III 樹狀數組

BZOJ4994 [Usaco2017 Feb]Why Did the Cow Cross the Road III 樹狀數組

lin size ros spa 題意 lld get html 統計

歡迎訪問~原文出處——博客園-zhouzhendong

去博客園看該題解


題目傳送門 - BZOJ4994


題意概括

  給定長度為2N的序列,1~N各處現過2次,i第一次出現位置記為ai,第二次記為bi,求滿足ai<aj<bi<bj的對數。

  n<=100000(這個數據範圍是我湊出來的,但是我沒試過更小的範圍,BZOJ上沒寫數據範圍(截止2017-08-24))


題解

  水題,開一個樹狀數組在線解決。

  比如我們順著掃過去,當到達一個 bj 時,我們求滿足條件的 ai,bi 個數,其實就是求 bi~bj 之間有幾個數出現一次而且是第一次出現。

  所以我們開樹狀數組維護。

  我順著做過去,對於每一個數字i,在ai的地方+1,到了bi就在ai的地方-1,並統計區間ans,累加即可。


代碼

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long LL;
const int N=100000+5;
int n,c[N*2],f[N];
LL ans=0;
int lowbit(int x){
	return x&-x;
}
void add(int x,int d){
	for (;x<=n*2;x+=lowbit(x))
		c[x]+=d;
}
int sum(int x){
	int ans=0;
	for (;x>0;x-=lowbit(x))
		ans+=c[x];
	return ans;
}
int main(){
	scanf("%d",&n);
	memset(c,0,sizeof c);
	memset(f,0,sizeof f);
	for (int i=1,x;i<=n*2;i++){
		scanf("%d",&x);
		if (!f[x]){
			f[x]=i;
			add(i,1);
		}
		else {
			ans+=sum(i-1)-sum(f[x]);
			add(f[x],-1);
		}
	}
	printf("%lld",ans);
	return 0;
}

  

BZOJ4994 [Usaco2017 Feb]Why Did the Cow Cross the Road III 樹狀數組