图片说明
题意:每次询问给出L,R,问[L,R]中选择一个子集求和,无法凑出的最小正整数是多少;

思路:首先,如果没有1,那么;
假设现在能组成,且内有,那么就能凑出,即凑出,然后继续凑;
反之若内不存在,则无法凑出的最小正整数就是
x的增长速度是指数级的,因此最多次就出来了。

询问两个区间总和之差,需要用区间权值线段树,即可持久化线段树
复杂度:

记录的是第个版本的线段树,每次建个新的线段树需要重新开个点。

MyCode:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+7,maxm=2e5+7,N=1e5+7;
typedef long long int ll;
typedef unsigned long long ull;
struct node{
    int lt,rt;
    ll sum;
}t[maxn*31];
int tot;
void modify(int &x,int l,int r,int v) {
    t[++tot]=t[x];
    x=tot;
    t[x].sum+=v;
    if(l==r) return;
    int mid=l+r>>1;
    if(v<=mid) modify(t[x].lt,l,mid,v);
    else modify(t[x].rt,mid+1,r,v);
}
ll query(int x,int y,int l,int r,ll v) {
    if(l==r) return t[x].sum-t[y].sum;
    int mid=l+r>>1;
    if(v<=mid) return query(t[x].lt,t[y].lt,l,mid,v);
    else return query(t[x].rt,t[y].rt,mid+1,r,v)+ t[t[x].lt].sum - t[t[y].lt].sum;
}
int rt[maxn];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n,Q,l,r;
    ll ans(0),tmp;
    cin>>n>>Q;
    for(int i=1,x;i<=n;++i) {
        cin>>x;
        modify(rt[i]=rt[i-1],1,1000000000,x);
    }
    while(Q--) {
        cin>>l>>r;
        l=(ans+l)%n+1;
        r=(ans+r)%n+1;
        if(l>r) swap(l,r);
        ans=0;
        while(true) {
            tmp=query(rt[r],rt[l-1],1,1000000000,ans+1);
            if(tmp==ans) break;
            ans=tmp;
        }
        cout<<++ans<<'\n';
    }
    return 0;;
}