zoukankan      html  css  js  c++  java
  • bzoj 4994: [Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组_排序

    Description

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

    题解: 

    方法一:


    搞一个KDtree,数一下点即可. 

    方法二: 

    对于每个数存一下左端点 $l[a]$ 与右端点 $r[a]$, 按照左端点从小到大进行排序. 

    枚举到每个数字,就将左端点对应的桶 ++, 右端点对应的桶 --,每次对答案的更新为 $sum[l]$ - $sum[r]$. 

    为什么呢 ? 

    假设左端点的 $sum$ 为 $a$, 右端点的 $sum$ 为 $b$.

    那么, 说明在左端点这个位置上有 $a$ 个数字区间已经启动,却没有终止(感性理解一下).

    而 $a-b$ 则代表在 $[l[a],r[a]]$ 区间中终止的个数. 这不就是会对该区间有贡献的个数吗 ?

    前缀和用树状数组维护即可.  

     code:

    #include<bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define maxn 200001
    using namespace std;
    int arr[maxn],l[maxn],r[maxn],A[maxn],C[maxn]; 
    int cmp(int a,int b)
    {
        return l[a]<l[b]; 
    }
    int lowbit(int t)
    {
        return t&(-t); 
    } 
    void update(int x,int delta)
    {
        while(x<maxn) C[x]+=delta,x+=lowbit(x); 
    }
    int query(int x)
    {
        int tmp=0;
        while(x>0) tmp+=C[x],x-=lowbit(x); 
        return tmp; 
    }
    int main(){
       //  setIO("input");
        int n,m;
        scanf("%d",&n),m=(n<<1) ;
        for(int i=1,a;i<=m;++i)
        {
            scanf("%d",&a); 
            if(l[a]) 
                r[a]=i;
            else 
                l[a]=i; 
        }
        for(int i=1;i<=n;++i) A[i]=i;
        sort(A+1,A+1+n,cmp); 
        int ans=0; 
        for(int i=1;i<=n;++i)
        {
            int cur=A[i],a; 
            a=query(l[cur])-query(r[cur]);    
            ans+=a; 
            update(l[cur],1),update(r[cur],-1); 
        }
        printf("%d
    ",ans); 
        return 0; 
    }
    

      

  • 相关阅读:
    Django进阶之CSRF
    Django进阶之session
    simple_tag,filte,分页以及cookie和装饰器
    Django 中url补充以及模板继承
    Django补充及初识Ajax
    2016年12月20日感想
    Docker的镜像
    继续Django
    jS正则和WEB框架Django的入门
    Docker的容器
  • 原文地址:https://www.cnblogs.com/guangheli/p/10951609.html
Copyright © 2011-2022 走看看