zoukankan      html  css  js  c++  java
  • BZOJ 4408: [Fjoi 2016]神秘数 [主席树]

    传送门

    题意:

    一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数。例如S={1,1,1,4,13},
    8无法表示为集合S的子集的和,故集合S的神秘数为8。
    现给定n个正整数a[1]..a[n],m个询问,每次询问给定一个区间[l,r](l<=r),求由a[l],a[l+1],…,a[r]所构成的可重复数字集合的神秘数。


    咦,神秘数好熟悉啊

    最优集合?

    那么如何求神秘数就很清楚了,当前$now$,就找$le now+1$的数

    询问区间?难道用主席树嘛

    然后看了下题解 发现的确是主席树,每次$le now$前缀和看看能不能$+1 ge now$来更新$now$

    复杂度?

    之前和现在为$a,b$,下次必定加上$a< <b$的数。最多$O(logsum a)$次

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define lc(x) t[x].l
    #define rc(x) t[x].r
    typedef long long ll;
    const int N=1e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,Q,a[N],mp[N],m;
    inline void inimp(){
        sort(mp+1,mp+1+m);
        int p=0; mp[++p]=mp[1];
        for(int i=2;i<=m;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i];
        m=p;
    }
    inline int Bin(int v){
        int l=1,r=m;
        while(l<=r){
            int mid=(l+r)>>1;
            if(v==mp[mid]) return mid;
            else if(v<mp[mid]) r=mid-1;
            else l=mid+1;
        }
        return 0;
    }
    struct Node{
        int l,r,sum;
    }t[N*30];
    int root[N],sz;
    void fIns(int &x,int l,int r,int p){//printf("ins %d %d %d %d
    ",x,l,r,p);
        t[++sz]=t[x];x=sz;
        t[x].sum+=mp[p];
        if(l==r) return;
        int mid=(l+r)>>1;
        if(p<=mid) fIns(lc(x),l,mid,p);
        else fIns(rc(x),mid+1,r,p);
    }
    int fQue(int x,int y,int l,int r,int ql,int qr){//printf("que %d %d %d %d  %d %d
    ",x,y,mp[l],mp[r],ql,qr);if(l==4 && r==4 && qr==8) return 0;
        if(qr<mp[l] || ql>mp[r]) return 0;
        if(ql<=mp[l]&&mp[r]<=qr) return t[y].sum-t[x].sum;
        else{
            int re=0,mid=(l+r)>>1;
            if(ql<=mp[mid]) re+=fQue(lc(x),lc(y),l,mid,ql,qr);
            if(mp[mid]<qr) re+=fQue(rc(x),rc(y),mid+1,r,ql,qr);
            return re;
        }
    }
     
    int main(){
        //freopen("in","r",stdin);
        n=read();
        for(int i=1;i<=n;i++) a[i]=mp[++m]=read();
        inimp();
        //for(int i=1;i<=n;i++) printf("a %d %d
    ",a[i],Bin(a[i]));
        for(int i=1;i<=n;i++) a[i]=Bin(a[i]),root[i]=root[i-1],fIns(root[i],1,m,a[i]);//puts("endIns");
        Q=read();
        while(Q--){
            int l=read(),r=read();
            int now=1;
            while(true){
                int _=fQue(root[l-1],root[r],1,m,1,now);
                if(_<now) break;
                else now=_+1;
            }
            printf("%d
    ",now);
        }
    }
  • 相关阅读:
    如何用命令将本地项目上传到github
    Mysql基本命令一
    Mysql基本命令二
    PDO操作数据库
    PHP分页
    JQuery中$.ajax()方法参数详解
    基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
    IE浏览器兼容问题
    购物车的实现方式
    JS学习之路
  • 原文地址:https://www.cnblogs.com/candy99/p/6540101.html
Copyright © 2011-2022 走看看