zoukankan      html  css  js  c++  java
  • bzoj4299: Codechef FRBSUM

    这是一道神题啊

    首先假设对于当前区间,补一个0,然后数都排好序

    现在把第i个数加进来,假设对于0~x都可以表示出来

    对于只选i一个的方案,我们用i+0表示,也就是说加进来的数可以和0~x相加组成更大的数

    考虑连续的问题,我们发现加进来的那些数可以看成一段区间,而这段区间能够起到贡献当且仅当他和当前0~x的区间重合或无缝衔接

    也就是说i要满足<=x+1的限制

    具体怎么做呢,对于当前已经解决的0~x,我们需要的是1个小于等于x+1的数来拼起来

    先来求一次区间排完序后的前缀和,如果前缀和小于x+1,说明不存在一个新的小于等于x+1的数,结束

    否则说明可以拼接,最大值x变为前缀和

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    struct chairman_tree
    {
        int lc,rc,c;
    }tr[4100000];int trlen,rt[110000];
    int maketree(int now,int l,int r,int p)
    {
        if(now==0)
        {
            now=++trlen;
            tr[now].lc=tr[now].rc=0;
            tr[now].c=0;
        }
        tr[now].c+=p;
        if(l==r)return now;
        else
        {
            int mid=(l+r)/2;
            if(p<=mid)tr[now].lc=maketree(tr[now].lc,l,mid,p);
            else      tr[now].rc=maketree(tr[now].rc,mid+1,r,p);
        }
        return now;
    }
    int merge(int x,int y)
    {
        if(x==0||y==0)return x+y;
        tr[x].c+=tr[y].c;
        tr[x].lc=merge(tr[x].lc,tr[y].lc);
        tr[x].rc=merge(tr[x].rc,tr[y].rc);
        return x;
    }
    int getsum(int x,int y,int l,int r,int ll,int rr)
    {
        if(ll==l&&rr==r)return tr[y].c-tr[x].c;
        int mid=(l+r)/2;
             if(rr<=mid)  return getsum(tr[x].lc,tr[y].lc,l,mid,ll,rr);
        else if(mid+1<=ll)return getsum(tr[x].rc,tr[y].rc,mid+1,r,ll,rr);
        else return getsum(tr[x].lc,tr[y].lc,l,mid,ll,mid)+getsum(tr[x].rc,tr[y].rc,mid+1,r,mid+1,rr);
    }
    
    int a[110000];
    int main()
    {
        int n,m=100;
        scanf("%d",&n); trlen=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]), m+=a[i];
        for(int i=1;i<=n;i++)
        {
            rt[i]=maketree(rt[i],1,m,a[i]);
            rt[i]=merge(rt[i],rt[i-1]);
        }
        
        int Q,l,r;
        scanf("%d",&Q);
        while(Q--)
        {
            scanf("%d%d",&l,&r);
            int mx=0,d;
            while(1)
            {
                d=getsum(rt[l-1],rt[r],1,m,1,mx+1);
                if(mx+1>d)break;
                mx=d;
            }
            printf("%d
    ",mx+1);
        }
        
        return 0;
    }
  • 相关阅读:
    SE78添加图片,比如smartforms用的…
    Smartforms
    将文件上传到FTP服务器
    【转自ITPUB】SYNONYM关于underlying table权限的小小发现
    alter session set current_schema=Schema
    exportDISPLAY=:0.0的解释
    如何通过使用Xmanager的图形化界面修改系统
    Xms Xmx PermSize MaxPermSize 区别
    oracle中schema指的是什么?
    oracle表空间查询
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10224471.html
Copyright © 2011-2022 走看看