ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021-ICPC昆明站M-Stone Games(思维+主席树)

2021-05-06 15:29:31  阅读:339  来源: 互联网

标签:Stone int 凑出 rc ICPC Games ans 区间 root


题目链接

题意:给定了n堆石子每堆的数量是[1,1e9]的整数,q次询问,每次给出区间[l,r],可以选择[l,r]区间的石子堆加起来凑出一个数x,问最小的无法被凑出的数是多少?
(每次询问中,每堆石子最多选择1次,此题强制在线)

分析:
对于[l,r]区间,我们把石子数放进一个桶里。
首先0肯定可以被凑到,因为可以每堆都不选。
此时我们关心1是否能被凑到,我们查询桶内 值在[0,1]区间的数的和,
假设和为x,(也就是有x1), 那么说明我们可以凑出[0,x]区间的所有数

(当然,如果此时x的值是0,那么说明1不能被凑到,算法退出,答案就是1)

于是关心x+1能否被凑到,我们查询桶内 值在[0,x+1]区间的数的和,
假设和为x1,设[0,x+1]没有参与合成x的数的和为sum,
那么有x+sum=x1,由于我们已经可以凑出[0,x]的每个数了,所以我们可以凑出[0,x+sum]的每个数。 次数如果sum==0,那么说明x+1无法被凑出。

思路:建主席树维护桶的区间和。 每次取出root[r]-root[l-1]这棵树,查询区间和。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 1e6+10;
const int mx = 31;
const int mod = 1e9+7;
const ll inf = 34359738370;
const int INF = 1e9+7;
//给定整数数列  每次询问一个区间[l,r] 选取这个区间的一个子区间凑成一个数  问最小的无法被凑出的数x是多少
//主席树 维护桶的区间和  查询区间和
ll tree[maxn*mx];
int lc[maxn*mx],rc[maxn*mx],root[maxn],cnt=0;
inline void updata(int &rt,int last,int l,int r,int x)
{
    rt=++cnt;
    tree[rt]=tree[last]+x;
    lc[rt]=lc[last],rc[rt]=rc[last];
    if(l == r) return ;
    int mid=(l+r)>>1;
    if(x<=mid) updata(lc[rt],lc[last],l,mid,x);
    else updata(rc[rt],rc[last],mid+1,r,x);
}
inline ll query(int rt1,int rt2,int l,int r,ll vr )
{
    if(1<= l && r<=vr) return tree[rt1]-tree[rt2];
    int mid=(l+r)>>1;
    if(vr<=mid) return query(lc[rt1],lc[rt2],l,mid,vr);
    if(1>mid) return query(rc[rt1],rc[rt2],mid+1,r,vr);
    return query(lc[rt1],lc[rt2],l,mid,vr)+query(rc[rt1],rc[rt2],mid+1,r,vr);
}
int n,q;
int main()
{
    scanf("%d %d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        updata(root[i],root[i-1],1,INF,x);
    }
    ll ans=0;
    int l,r;
    while(q--)
    {
        scanf("%d %d",&l,&r);
        l=(l+ans)%n+1;
        r=(r+ans)%n+1;
        if(l>r) swap(l,r);
        ans=0;//假设已经扩展到[0,ans] 查询[0,ans+1]桶内所有元素的和t 是否大于ans  如果是 那么可以凑出[0,t]
        while(1)
        {
            ll t=query(root[r],root[l-1],1,INF,ans+1);
            if(t==ans) break;//无法凑出ans+1这个数
            ans=t;
        }
        printf("%lld\n",++ans);
    }
    return 0;
}

标签:Stone,int,凑出,rc,ICPC,Games,ans,区间,root
来源: https://blog.csdn.net/qq_46030630/article/details/116454224

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有