【主席树】2021 ICPC 昆明 M.Stone Games
2021-04-12 18:43:00 # ACM

答案是对着这段区间 $[L,R]$ 不断询问直到不存在 $x+1$ 得来的;

例如一个区间有为 $1,2,4,4$;

首先询问 $1$,发现存在 $1$,$ans = 1$;

然后询问 $ans+1 = 2$,发现存在 $2$,则 $[1,3]$ 都能凑出,$ans = 3$;

接着询问 $ans+1 = 4$,发现存在两个 $4$,则 $[1,11]$ 都能凑出,$ans = 11$;

实际上 “发现存在” 这一步操作就是查找区间 $[1,ans+1]$ 的和 $sum$ 为多少,然后更新 $ans = sum$;

答案就是 $++ans$;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <bits/stdc++.h>
using namespace std;
#define MS 1000009
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define MAXN 1000000000

int n,m,k;
int tot;
int rtpos[MS];
struct node{
int l,r;
LL val;
}p[MS*40];

void push_up(int rt){
p[rt].val = p[p[rt].l].val + p[p[rt].r].val;
}

int update(int lart,int l,int r,LL pos){
int rt = ++tot;
p[rt] = p[lart];
if(l == r){
p[rt].val += pos;
return rt;
}
int m = l+r>>1;
if(m >= pos) p[rt].l = update(p[lart].l,l,m,pos);
else p[rt].r = update(p[lart].r,m+1,r,pos);
push_up(rt);
return rt;
}

LL getsum(int L,int R,int l,int r,LL tar){
if(l == r) return p[R].val - p[L].val;
int m = l+r>>1;
if(m >= tar) return getsum(p[L].l,p[R].l,l,m,tar);
else return p[p[R].l].val - p[p[L].l].val + getsum(p[L].r,p[R].r,m+1,r,tar);
}

int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i=1;i<=n;i++){
LL x;
cin >> x;
rtpos[i] = update(rtpos[i-1],1,MAXN,x);
}
LL ans = 0;
while(m--){
int L,R;
cin >> L >> R;
L = (L+ans)%n+1;
R = (R+ans)%n+1;
if(L > R) swap(L,R);
ans = 0;
while(1){
LL tmp = getsum(rtpos[L-1],rtpos[R],1,MAXN,ans+1);
if(tmp == ans) break;
ans = tmp;
}
cout << ++ans << "\n";
}


return 0;
}

Prev
2021-04-12 18:43:00 # ACM
Next