• ●BZOJ 4408 [Fjoi 2016]神秘数


    题链

    主席树
    首先,对于一些数来说,
    如果可以我们可以使得其中的某些数能够拼出 1~ret
    那么此时的ANS(神秘数)= ret+1
    然后考虑,如果此时存在另一个数小于等于 ANS,(设该数为 x)
    则一定可以在原来的1~ret的基础上拼出 1~ret+x
    即 ANS 可以更新为 ret+x+1
    所以具体的操作就是:
    每次查询区间内小于ANS的数的和(SUM),然后如果SUM大于ANS,则更新ANS为SUM+1。
    不断上述操作直到SUM<ANS为止。
    主席数实现在序列区间中查询权值区间的和。
    代码:
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100500
    using namespace std;
    int A[MAXN],tmp[MAXN];
    int N,M,tnt;
    struct CMT{
        long long sum[MAXN*20];
        int rt[MAXN],ls[MAXN*20],rs[MAXN*20],sz;
        void Insert(int v,int &u,int l,int r,int p){
            u=++sz; ls[u]=ls[v]; rs[u]=rs[v]; 
            sum[u]=sum[v]; sum[u]+=tmp[p];
            if(l==r) return;
            int mid=(l+r)>>1;
            if(p<=mid) Insert(ls[v],ls[u],l,mid,p);
            else Insert(rs[v],rs[u],mid+1,r,p);
        }
        long long Query(int v,int u,int l,int r,int al,int ar){
            if(al<=l&&r<=ar) return sum[u]-sum[v];
            int mid=(l+r)>>1; long long ret=0;
            if(al<=mid) ret+=Query(ls[v],ls[u],l,mid,al,ar);
            if(mid<ar) ret+=Query(rs[v],rs[u],mid+1,r,al,ar);
            return ret;
        }
        void Build(){
            for(int i=1;i<=N;i++)
                Insert(rt[i-1],rt[i],1,tnt,A[i]);
        }
    }DT;
    int main(){
    //  freopen("/home/noilinux/Documents/Code/BZOJ/4408.in","r",stdin);
    //  printf("BEGIN.
    ");
        scanf("%d",&N);
        for(int i=1;i<=N;i++)
            scanf("%d",&A[i]),tmp[i]=A[i];
        sort(tmp+1,tmp+N+1);
        tnt=unique(tmp+1,tmp+N+1)-tmp-1;
        for(int i=1;i<=N;i++)
            A[i]=lower_bound(tmp+1,tmp+tnt+1,A[i])-tmp;
        scanf("%d",&M);
        DT.Build(); long long ANS,ret,p;
        for(int i=1,l,r;ANS=0,ret=0,i<=M;i++){
            scanf("%d%d",&l,&r);
            while(ANS<ret+1){
                ANS=ret+1;
                p=upper_bound(tmp+1,tmp+tnt+1,ANS)-tmp-1;
                ret=DT.Query(DT.rt[l-1],DT.rt[r],1,tnt,1,p);
            }
            printf("%lld
    ",ANS);
        }
        return 0;
    }
    

      

     
  • 相关阅读:
    【LeetCode】面试题59
    【LeetCode】面试题57
    【LeetCode】面试题57
    Chrome查看Markdown并转为PDF
    【LeetCode】232. 用栈实现队列
    【LeetCode】27. 移除元素
    【LeetCode】1323. 6 和 9 组成的最大数字
    【LeetCode】167. 两数之和 II
    第14条:在公有类中使用访问方法而非公有域
    Android Studio项目中三种依赖的添加方式
  • 原文地址:https://www.cnblogs.com/zj75211/p/8092630.html
Copyright © 2020-2023  润新知