zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    防止sql注入的方法
    二叉树的LCA(最近公共祖先)算法
    二叉树的计算
    @RestController和@Controller注解的区别
    单调栈与单调队列
    java中删除list指定元素遇到的问题
    随机打乱数组
    Mysql基本操作
    二叉树的构建
    synchronized修饰方法和对象的区别
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ4994.html
Copyright © 2011-2022 走看看