BZOJ4994 [Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组
欢迎访问~原文出处——博客园-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; }