[BZOJ4408][FJOI2016]神秘数(主席树)

17 篇文章 0 订阅
12 篇文章 0 订阅

题目:

我是超链接

题解:

如果[1,x]可以取到,我们加入一个数y,如果y<=x+1,那么我们有新的取数集合[1,x+y];如果y>x+1,那么x+1还是取不到啊,这样我们就有了一个暴力的思路

进一步考虑,对于一个还未发展的数列,我们的取值范围是[1,x],x=0,ans=1,我们可以把权值<=ans的数字加起来,和设为y
如果这时ans<=y,就是说除了凑成[1,x]的数外,我们还能找出一个数<=ans,这样取数集合是[1,y];
如果这时ans>y,就是说除了凑成[1,x]的数外,我们找不出任何一个数字了,这样取数集合是[1,x],ans就取不到咯
我们可以依据这种方法求ans,建一棵权值线段树,要维护区间和的话,用主席树就好啦

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100005;
int sz,root[N],b[N],a[N],p[N];
struct hh{int l,r,w,sum;}t[N*20];
void insert(int &now,int l,int r,int x,int v)
{
    t[++sz]=t[now]; now=sz;
    t[now].w++; t[now].sum+=v;
    if (l==r) return;
    int mid=(l+r)>>1;
    if (x<=mid) insert(t[now].l,l,mid,x,v);
    else insert(t[now].r,mid+1,r,x,v);
}
int qurry(int x,int y,int l,int r,int lrange,int rrange)
{
    if (rrange<lrange) return 0;
    if (lrange<=l && rrange>=r) return t[y].sum-t[x].sum;
    int mid=(l+r)>>1,ans=0;
    if (lrange<=mid) ans+=qurry(t[x].l,t[y].l,l,mid,lrange,rrange);
    if (rrange>mid) ans+=qurry(t[x].r,t[y].r,mid+1,r,lrange,rrange); 
    return ans;
}
int main()
{
    int s=0,n,maxx=0,m;
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]),maxx+=a[i],b[++s]=a[i];
    sort(b+1,b+s+1);
    s=unique(b+1,b+s+1)-b-1;
    for (int i=1;i<=n;i++) p[i]=lower_bound(b+1,b+s+1,a[i])-b;
    for (int i=1;i<=n;i++)
    {
        root[i]=root[i-1];
        insert(root[i],1,s,p[i],b[p[i]]);
    }
    scanf("%d",&m);
    while (m--)
    {
        int x,y,ans=1;
        scanf("%d%d",&x,&y);
        while (1)
        {
            int t=qurry(root[x-1],root[y],1,s,1,upper_bound(b+1,b+s+1,ans)-b-1);
            if (t>=ans) ans=t+1;
            else break;
        }
        printf("%d\n",ans);
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值