zoukankan      html  css  js  c++  java
  • BZOJ4299 Codechef FRBSUM(主席树)

      感觉非常不可做,于是考虑有什么奇怪的性质。

      先考虑怎么求子集和mex。将数从小到大排序,假设已经凑出了0~n的所有数,如果下一个数>n+1显然mex就是n+1了,否则若其为x则可以凑出1~n+x所有数。

      对于区间查询,建棵主席树即可,每次查询权值线段树上lastn+2~n+1的区间,用区间和更新n,如果这段区间没有数则mex为n+1。因为每次n的增量都是在lastn+2~n+1这一段的,所以每查询两次n会翻一倍以上,复杂度O(nlog2n)。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 100010
    #define inf 1000000000
    int n,m,a[N],root[N],cnt;
    struct data{int l,r,x;
    }tree[N<<6];
    void ins(int &k,int l,int r,int x)
    {
        tree[++cnt]=tree[k],k=cnt;tree[k].x+=x;
        if (l==r) return;
        int mid=l+r>>1;
        if (x<=mid) ins(tree[k].l,l,mid,x);
        else ins(tree[k].r,mid+1,r,x);
    }
    int query(int x,int y,int l,int r,int p,int q)
    {
        if (!y) return 0;
        if (p==l&&q==r) return tree[y].x-tree[x].x;
        int mid=l+r>>1;
        if (q<=mid) return query(tree[x].l,tree[y].l,l,mid,p,q);
        else if (p>mid) return query(tree[x].r,tree[y].r,mid+1,r,p,q);
        else return query(tree[x].l,tree[y].l,l,mid,p,mid)+query(tree[x].r,tree[y].r,mid+1,r,mid+1,q);
    }
    int getans(int l,int r)
    {
        int sum=0,last=-1;
        while (sum<inf)
        {
            int x=query(root[l],root[r],1,inf,last+2,sum+1);
            if (!x) return sum+1;
            else last=sum,sum+=x;
        }
        return sum;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4299.in","r",stdin);
        freopen("bzoj4299.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) a[i]=read();
        for (int i=1;i<=n;i++)
        {
            root[i]=root[i-1];
            ins(root[i],1,inf,a[i]);
        }
        m=read();
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            printf("%d
    ",getans(x-1,y));
        }
        return 0;
    }
  • 相关阅读:
    虚拟目录的配置
    php7.0.24-nts配置步骤
    什么是PHP
    网络篇-NSURLSessionDownloadTask上传
    网络篇-NSURLConnection原生上传
    网络篇-NSURLConnection进度下载
    网络篇-NSURLSessionDownloadTask进度下载(续上节)
    网络篇-NSURLSession介绍
    网络篇-解析XML
    多线程篇-RunLoop
  • 原文地址:https://www.cnblogs.com/Gloid/p/9839785.html
Copyright © 2011-2022 走看看