# 2020icpc Kunming Stone Games (persistent weight segment tree)

Give you n positive integers and m queries. Each query gives an L, r. Ask how many positive integers you can't represent with the smallest number in the interval [l, r] (you can only select some numbers from the selected interval for summation, and each number can only be selected once at most)

For example, if the number in the selected interval is 1, 2, 3, 4, 5 and 6, it is easy to know that the six numbers 1, 2, 3, 4, 5 and 6 can be represented, and the smallest positive integer that cannot be represented is 7

Analysis: if the interval we selected is [l, R], we already know that this interval can represent all numbers in 0~ans (of course, any interval can represent 0), then we sum the numbers in 0~ans+1 to get a sum, then any number in 0~sum can be represented by the numbers in [l, R]

Proof: under the above conditions, we already know that this interval can represent all the numbers in 0~ans. it may be assumed that the set used to represent all the numbers in 0~ans is a (all numbers have been used, not every number). We are subordinate to the interval [l, R] and do not belong to the number in set A. choose any number k < ANS, Adding it to set a can immediately make the range that set a can represent become 0~ans+k. for example, to represent ans+i (I < = k), use the number in the original set to represent ans+i-k, and then add K. at this time, we can add any number s < = ans + k that belongs to interval [l, R] and does not belong to set a, and then continue to expand the range that the interval can represent, Until the interval we can currently represent is ANS and belongs to the interval   [l, R] and all the numbers with values less than or equal to ans are added to get ans, but is ans+1 the smallest number that we can't represent? Of course not. ans+1 may be composed of numbers less than or equal to ans, or it may be directly composed of ans+1. Therefore, when the interval we can represent is ANS and belongs to the interval   [l, R] and when all the numbers with values less than or equal to ans are added to still get ans, it is also necessary to judge whether ans+1 exists. If ans+1 does not exist, we directly get that the smallest number that cannot be represented is ans+1. If ans+1 exists, we will expand the current representation range to 0~ans+1, and then continue to repeat the above process, That is, it is directly equivalent to summing the numbers in the interval at 0~ans+1 every time until the sum remains unchanged to get our smallest unrepresentatible value.

Therefore, we need to use a weighted persistent segment tree to expand the range of numbers we can represent until we get the answer.

Here is the code:

```#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
const int N=25000010,M=1e6+10;
int a[M],ln[N],rn[N],idx,root[M];
long long sum[N];
vector<int> alls;
int find(long long x)
{return lower_bound(alls.begin(),alls.end(),x)-alls.begin()+1;}
void pushup(int id){sum[id]=sum[ln[id]]+sum[rn[id]];}
void update_point(int pre,int id,int x,int val,int l,int r)
{
ln[id]=ln[pre];rn[id]=rn[pre];sum[id]=sum[pre];
if(l==r)
{
sum[id]+=val;
return ;
}
int mid=l+r>>1;
if(x<=mid) ln[id]=++idx,update_point(ln[pre],ln[id],x,val,l,mid);
else rn[id]=++idx,update_point(rn[pre],rn[id],x,val,mid+1,r);
pushup(id);
}
long long query_interval(int pre,int id,int L,int R,int l,int r)
{
if(l>=L&&r<=R) return sum[id]-sum[pre];
int mid=l+r>>1;
long long ans=0;
if(mid>=L) ans+=query_interval(ln[pre],ln[id],L,R,l,mid);
if(mid+1<=R) ans+=query_interval(rn[pre],rn[id],L,R,mid+1,r);
return ans;
}
signed main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),alls.push_back(a[i]);
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
for(int i=1;i<=n;i++) a[i]=find(a[i]);
root=++idx;
int size=alls.size();
for(int i=1;i<=n;i++)
{
root[i]=++idx;
update_point(root[i-1],root[i],a[i],alls[a[i]-1],0,size);
}
int ll,rr,l,r;
long long ans=0,tans=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
ll=min((l+ans)%(n)+1,(r+ans)%(n)+1);
rr=max((l+ans)%(n)+1,(r+ans)%(n)+1);
ans=tans=0;
while(1)
{
int t=find(ans+1);
if(alls[t-1]!=ans+1) t--;
tans=query_interval(root[ll-1],root[rr],0,t,0,size);
if(tans==ans) break;
ans=tans;

}
ans++;
printf("%lld\n",ans);
}
return 0;
}```

Posted on Wed, 10 Nov 2021 19:43:15 -0500 by vlince