• [ USACO 2017 FEB ] Why Did the Cow Cross the Road III (Gold)


    (\)

    (Description)


    给定长度为(2N)的序列,(1 ext ~N)各出现过(2)次,(i)第一次出现位置记为(a_i),第二次记为(b_i),求满足(a_i<a_j<b_i<b_j)((i,j))对数。

    • (Nin [1,10^5])

    (\)

    (Solution)


    考虑以一个数作为(i)出现在答案里,对应的(j)应满足(a_jin (a_i,b_i),b_j>b_i)。也就是说,我们需要对每一个数统计它两次出现的位置构成的区间里,有多少个数字是第一次出现。

    考虑树状数组的做法,第一次遇到一个数时,在出现位置打标记,记录下这个数第一次出现的位置,便于询问。

    当第二次遇到这个数时,直接查询区间((a_i,b_i))的区间和即可。因为这个数已经出现了两次,不能对后续的询问做出贡献了,所以要将之前的打标记处撤销标记。

    (\)

    (Code)


    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 50010
    #define R register
    #define gc getchar
    using namespace std;
    
    inline int rd(){
      int x=0; bool f=0; char c=gc();
      while(!isdigit(c)){if(c=='-')f=1;c=gc();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
      return f?-x:x;
    }
    
    int n,ans,p[N];
    
    struct BIT{
      int c[N];
      inline int lowbit(int x){return x&-x;}
      inline void add(int p,int x){for(;p<=n;p+=lowbit(p))c[p]+=x;}
      inline int sum(int p){
        int res=0;
        for(;p;p-=lowbit(p)) res+=c[p];
        return res;
      }
    }bit;
    
    int main(){
      n=rd()<<1;
      for(R int i=1,x;i<=n;++i){
        x=rd();
        if(!p[x]) bit.add((p[x]=i),1);
        else ans+=bit.sum(i)-bit.sum(p[x]),bit.add(p[x],-1);
      }
      printf("%d
    ",ans);
      return 0;
    }
    
    
  • 相关阅读:
    同行——冲刺集合!!!
    团队作业第六次——事后诸葛亮
    同行——冲刺总结
    同行——冲刺day7(11.14)
    同行——测试随笔
    同行——冲刺day6(11.13)
    同行——冲刺day5(11.12)
    同行——冲刺day4(11.11)
    同行——冲刺day3(11.10)
    同行——冲刺day2(11.9)
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9740980.html
Copyright © 2020-2023  润新知