zoukankan      html  css  js  c++  java
  • bzoj3192: [JLOI2013]删除物品(树状数组)

      既然要从一个堆的堆顶按顺序拿出来放到第二个堆的堆顶,那么我们就可以把两个堆顶怼在一起,这样从一个堆拿到另一个堆只需要移动指针就好了。

      换句话说,把1~n倒着,n+1到n+m正着,用一个指针把两个序列分开就好了,然后用树状数组维护哪些点被取过就好了...

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn=500010;
    int n, m;
    ll ans;
    int a[maxn], b[maxn], pos[maxn], tree[maxn];
    void read(int &k)
    {
        int f=1; k=0; char c=getchar();
        while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
        while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
        k*=f;
    }
    inline void add(int x, int delta){for(;x<=n;x+=x&-x) tree[x]+=delta;}
    inline int query(int x){int sum=0; for(;x;x-=x&-x) sum+=tree[x]; return sum;}
    int main()
    {
        read(n); read(m);
        for(int i=n;i;i--) read(a[i]), b[i]=a[i];
        for(int i=n+1;i<=n+m;i++) read(a[i]), b[i]=a[i];
        n+=m; for(int i=1;i<=n;i++) tree[i]=i&-i;
        sort(b+1, b+1+n);
        for(int i=1;i<=n;i++) a[i]=lower_bound(b+1, b+1+n, a[i])-b;
        for(int i=1;i<=n;i++) pos[a[i]]=i;
        int now=n-m;
        for(int i=n;i;i--)
        {
            if(pos[i]>now) ans+=query(pos[i]-1)-query(now);
            else ans+=query(now)-query(pos[i]);
            add(pos[i], -1); now=pos[i];
        }
        printf("%lld
    ", ans);
    }
    View Code

      貌似还可以用平衡树做,等会试试。

  • 相关阅读:
    四校联考【20171001】
    C语言基础知识
    页表和TLB
    python
    Cache组织方式
    On the Spectre and Meltdown Processor Security Vulnerabilities
    latex-组织文本
    深入理解计算机系统
    深入理解计算机系统-计算机系统漫游
    逻辑地址到物理地址的转换
  • 原文地址:https://www.cnblogs.com/Sakits/p/8017923.html
Copyright © 2011-2022 走看看