zoukankan      html  css  js  c++  java
  • Codechef ForbiddenSum

    Mike likes to invent new functions. The latest one he has invented is called ForbiddenSum. Let's consider how it can be calculated:

    You are given a set S of positive integers. The integers are not necessary distinct. ForbiddenSum of S equals to the minimal non-negative integer, that can't be returned by the algorithm described below:

    • Choose a random subset S' of S(it can be empty as well);
    • Calculate the sum of all the numbers of S' and assign it to the variable T;
    • Return the value of the variable T.

    I.e. if S = {1, 1, 3, 7}, the algorithm can return 0(S' = {}), 1(S' = {1}), 2(S' = {1, 1}), 3(S' = {3}), 4(S' = {1, 3}), 5(S' = {1, 1, 3}), but it can't return 6. So, ForbiddenSum of S equals to 6.

    Inventing of new function is not the only Mike's hobby. Also, he likes to collect rare and unusual arrays. He is going to share with you one of them.

    Formally, Mike gives you one array A, consisting of N positive integers. After that, he asks you M questions, two integers Li and Ri describe i'th question: What does ForbiddenSum of S={ALiALi+1, ..., ARi-1ARi} equal to?

    Input

    The first line contains the only integer N. The second line contains N integers - the array AA is 1-indexed.

    The third line contains the only integer M. The following M lines contain two integer numbers 1 ≤ Li ≤ Ri ≤ N each.

    Output

    Output should consists of M lines. The i'th line should contains the answer to the i'th question.

    Constraints

    1 ≤ NM ≤ 100,000

    1 ≤ Ai ≤ 109

    1 ≤ A1 + A2 + ... + AN ≤ 109

    Example

    Input:
    5
    1 2 4 9 10
    5
    1 1
    1 2
    1 3
    1 4
    1 5
    
    Output:
    2
    4
    8
    8
    8
    

    Explanation

    In the example test there are M=5 questions. We won't describe all of them, only two ones.

    The first question

    In the first test case S equals to {1}. The answer is 2, because we can recieve 1 in case the algorithm chooses S' = {1}. But there are no chances to receive 2.

    The second question

    In the first test case S equals to {1, 2}. The answer is 4, because we can recieve 1 in case the algorithm chooses S' = {1}, 2 in case the algorithm chooses S' = {2} and 3 in case the algorithm chooses S' = {1, 2}. But there are no chances to receive 4.

    中文题面在这: Mandarin Chinese 

    有一个性质是我随便口胡的虽然不知道怎么证明但是却用它A了这个题。

    那就是如果集合按数字大小排序之后,i是最小的满足a[1]+a[2]+...a[i]<a[i+1]-1,那么这个集合的forbidden sum为a[i+1]-1.

    这就相当于表示不了a[i+1]-1这个数了。

    而如果>=的话那么是可以接上的。

    于是就可以暴力做啦,对于每次询问,设最大能表示的数为num。

    一开始num都为0,然后每次查找区间内权值∈[1,num+1]的数的和,然后把num设为这个值。

    当然如果这个值==num的话,说明无法扩展了,输出num+1然后去管下一个询问就好了。

    这个的话用主席树比较好(当然你也可以用其他的)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define maxn 100005
    using namespace std;
    const int inf=1<<30;
    struct node{
        int lc,rc;
        int s;
    }nil[maxn*37];
    int n,m,ky,a[maxn],cnt=0;
    int rot[maxn];
    int le,ri,S,T,ans,pre;
    
    int update(int u,int l,int r){
        int ret=++cnt;
        nil[ret]=nil[u];
        nil[ret].s+=le;
        if(l==r) return ret;
        
        int mid=l+r>>1;
        if(le<=mid) nil[ret].lc=update(nil[ret].lc,l,mid);
        else nil[ret].rc=update(nil[ret].rc,mid+1,r);
        
        return ret;
    }
    
    int query(int x,int y,int l,int r){
        if(l>=le&&r<=ri) return nil[y].s-nil[x].s;
        int mid=l+r>>1,an=0;
        if(le<=mid) an+=query(nil[x].lc,nil[y].lc,l,mid);
        if(ri>mid) an+=query(nil[x].rc,nil[y].rc,mid+1,r);
        return an; 
    }
    
    inline void prework(){
        rot[0]=nil->lc=nil->rc=0;
        nil->s=0;
        
        for(int i=1;i<=n;i++){
            le=a[i];
            rot[i]=update(rot[i-1],1,1e9);
        }
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        
        prework();
        
        scanf("%d",&m);
        while(m--){
            scanf("%d%d",&S,&T);
            pre=-1,ans=0;
            while(ans>pre){
                pre=ans;
                le=1,ri=ans+1;
                ans=query(rot[S-1],rot[T],1,1e9);
            }
            
            printf("%d
    ",ans+1);
        }
        
        return 0;
    }
  • 相关阅读:
    java处理图片压缩、裁剪
    List按对象元素自定义排序
    List和数组汉字简单排序(转)
    欢迎访问我的个人博客,部分文章迁移
    Java资源免费分享,每日一更新,找到你心仪的吧
    今年的校招,Java好拿offer吗?
    【拥抱大厂系列】几个面试官常问的垃圾回收器,下次面试就拿这篇文章怼回去!
    2019,我的这一年,在校研究生做到年入20W,另送我的读者2000元现金红包
    深入理解Java虚拟机-如何利用VisualVM对高并发项目进行性能分析
    深入理解Java虚拟机-常用vm参数分析
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8398544.html
Copyright © 2011-2022 走看看