zoukankan      html  css  js  c++  java
  • [bzoj4994][Usaco2017 Feb]Why Did the Cow Cross the Road III_树状数组

    Why Did the Cow Cross the Road III bzoj-4994 Usaco-2017 Feb

    题目大意:给定一个长度为$2n$的序列,$1$~$n$个出现过两次,$i$第一次出现的位置记为$a_i$,第二次记为$b_i$,求满足$a_i<a_j<b_i<b_j$的个数。

    注释:$1le nle 10^5$。


    想法

    这个题有一个非常不一样的地方。

    我记得我之前做过的长成这样的题大概都是第一个位置+1,第二个位置-1即可。

    这个题我们只能对第一个位置进行操作。

    如果第一次碰见了这个数,就将当前位置+1

    如果是第二次碰见了这个数,我们先更新答案,然后把这个数第一个出现的位置-1即可。

    Code

    #include <bits/stdc++.h>
    #define N 100010 
    using namespace std; typedef long long ll;
    int tr[N<<2],vis[N],a[N<<1],n;
    inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
    int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
    inline int lowbit(int x) {return x&(-x);}
    void update(int x,int val) {for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=val;}
    ll query(int x) {ll ans=0; for(int i=x;i;i-=lowbit(i)) ans+=tr[i]; return ans;}
    int main()
    {
    	ll ans=0; n=rd()*2; for(int i=1;i<=n;i++) a[i]=rd(); for(int i=1;i<=n;i++)
    	if(!vis[a[i]]) update(i,1),vis[a[i]]=i;
    	else ans+=query(i)-query(vis[a[i]]),update(vis[a[i]],-1);
    	cout << ans << endl ;
    	return 0;
    }
    

    小结:树状数组是非常有用的啊,要熟练掌握才是。

  • 相关阅读:
    洛谷P1056_排座椅 贪心+桶排思想
    NOIP普及组相关
    洛谷P1464_Function 记忆化搜索
    Xcode的使用技巧
    MAC_XCODE清理
    输入框跟随键盘移动效果的实现
    #pragma的进阶用法
    iOS 逆向
    警告框
    UIImageView设置圆角的方式
  • 原文地址:https://www.cnblogs.com/ShuraK/p/10238707.html
Copyright © 2011-2022 走看看