对于一个连续的序列,例如[1 … k ] 那么一定能构造出 1到 1 + 2 + … + k 的数。
假设当前已经能够形成 [ 1 … x ] 的序列,此时x是最大能构造数,
接下来判断x+1是否能被构造,将小于等于(x + 1)的数的总和求出来,为sum.
- 如果sum != x,则能构造出[1 … sum] 序列。
- 否则,x+1就是最小不能构造的值。
一直迭代,直到得到答案。这个迭代类似于斐波那契。
初始x为0.
将区间中小于等于(x + 1)的值加起,用主席树维护。
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
//#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
#define ls(x) t[x].ls
#define rs(x) t[x].rs
#define sum(x) t[x].sum
struct LSegmentTree{
int ls,rs;
ll sum;
}t[N << 5];
int idx = 0,rt[N];
ll len = 1e9 + 10;
int update(int p,int l,int r,int v){
int root = ++idx;
ls(root) = ls(p),rs(root) = rs(p),sum(root) = sum(p) + v;
if(l == r) return root;
int mid = (l + r) >> 1;
if(v <= mid) ls(root) = update(ls(root),l,mid,v);
else rs(root) = update(rs(root),mid+1,r,v);
return root;
}
ll query(int lp,int rp,int l,int r,ll v){
if(l == r) return sum(rp) - sum(lp);
int mid = (l + r) >> 1;
if(v <= mid) return query(ls(lp),ls(rp),l,mid,v);
else return query(rs(lp),rs(rp),mid+1,r,v) + sum(ls(rp)) - sum(ls(lp));
}
signed main(){
int n,m; scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
int a; scanf("%d",&a);
rt[i] = update(rt[i-1],1,len,a);
}
ll last = 0;
while(m --){
int l,r; scanf("%d %d",&l,&r);
l = (l + last) % n + 1;
r = (r + last) % n + 1;
if(l > r) swap(l,r);
ll now = 0;
while(true){
ll ne = query(rt[l-1],rt[r],1,len,min(now+1,len));
if(ne == now) break;
now = ne;
}
printf("%lld\n",now+1);
last = now + 1;
}
return 0;
}