分块大法好
新手推荐阅读:「分块」数列分块入门1 – 9 by hzwer
练习:LibreOJ
“大段维护,局部朴素”
分块的调试检测技巧:
可以生成一些大数据,然后用两份分块大小不同的代码来对拍,还可以根据运行时间尝试调整分块大小,减小常数。
区间加法,单点查询
1 #include<bits/stdc++.h>
2 #define IL inline
3 #define R register int
4 #define ls(x) a[x].ch[0]
5 #define rs(x) a[x].ch[1]
6 #define fa(x) a[x].fa
7
8 using namespace std;
9 const int N=1e5+5,inf=0x3f3f3f3f;
10
11 IL int read() {
12 int f=1;char ch;
13 while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
14 int res=ch-'0';
15 while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
16 return res*f;
17 }
18
19 int n,a[N],ad[N],b[N],len;
20
21 IL void pre() {
22 len=sqrt(n);
23 for(R i=1;i<=n;++i) b[i]=(i-1)/len+1;
24 }
25
26 IL void add(int l,int r,int c) {
27 for(R i=l;i<=min(r,b[l]*len);++i) a[i]+=c;
28 if(b[l]!=b[r]) for(R i=(b[r]-1)*len+1;i<=r;++i) a[i]+=c;
29 for(R i=b[l]+1;i<=b[r]-1;++i) ad[i]+=c;
30 }
31
32 IL void query(int x) {
33 printf("%d\n",a[x]+ad[b[x]]);
34 }
35
36 int main() {
37 n=read();
38 for(R i=1;i<=n;++i) a[i]=read();
39 pre();
40 for(R i=1;i<=n;++i) {
41 int op=read(),l=read(),r=read(),c=read();
42 if(!op) add(l,r,c);
43 else query(r);
44 }
45 return 0;
46 }
区间加法,询问区间内小于某个值x的元素个数
//vector
1 #include<bits/stdc++.h>
2 #define IL inline
3 #define R register int
4 #define ls(x) a[x].ch[0]
5 #define rs(x) a[x].ch[1]
6 #define fa(x) a[x].fa
7
8 using namespace std;
9 const int N=1e5+5,inf=0x3f3f3f3f;
10
11 IL int read() {
12 int f=1;char ch;
13 while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
14 int res=ch-'0';
15 while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
16 return res*f;
17 }
18
19 int n,a[N],ad[N],b[N],len;
20 vector<int> s[N];
21
22 IL void pre() {
23 len=sqrt(n);
24 for(R i=1;i<=n;++i) b[i]=(i-1)/len+1,s[b[i]].push_back(a[i]);
25 for(R i=1;i<=b[n];++i)sort(s[i].begin(),s[i].end());
26 }
27
28 IL void reset(int x) {
29 s[x].clear();
30 for(R i=(x-1)*len+1;i<=min(x*len,n);++i) s[x].push_back(a[i]);
31 sort(s[x].begin(),s[x].end());
32 }
33
34 IL void add(int l,int r,int c) {
35 for(R i=l;i<=min(r,b[l]*len);++i) a[i]+=c;reset(b[l]);
36 if(b[l]!=b[r]) {
37 for(R i=(b[r]-1)*len+1;i<=r;++i) a[i]+=c;
38 reset(b[r]);
39 }
40 for(R i=b[l]+1;i<=b[r]-1;++i) ad[i]+=c;
41 }
42
43 IL void query(int l,int r,int x) {
44 int ans=0;
45 for(R i=l;i<=min(r,b[l]*len);++i)
46 if(a[i]+ad[b[i]]<x) ans++;
47 if(b[l]!=b[r])
48 for(R i=(b[r]-1)*len+1;i<=r;++i)
49 if(a[i]+ad[b[i]]<x) ans++;
50 for(R i=b[l]+1;i<=b[r]-1;++i) ans+=lower_bound(s[i].begin(),s[i].end(),x-ad[i])-s[i].begin();
51 printf("%d\n",ans);
52 }
53
54 int main() {
55 n=read();
56 for(R i=1;i<=n;++i) a[i]=read();
57 pre();
58 for(R i=1;i<=n;++i) {
59 int op=read(),l=read(),r=read(),c=read();
60 if(!op) add(l,r,c);
61 else query(l,r,c*c);
62 }
63 return 0;
64 }
区间加法,询问区间内小于某个值x的前驱(比其小的最大元素)
//set
1 #include<bits/stdc++.h>
2 #define IL inline
3 #define R register int
4 #define ls(x) a[x].ch[0]
5 #define rs(x) a[x].ch[1]
6 #define fa(x) a[x].fa
7
8 using namespace std;
9 const int N=1e5+5,inf=0x3f3f3f3f;
10
11 IL int read() {
12 int f=1;char ch;
13 while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
14 int res=ch-'0';
15 while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
16 return res*f;
17 }
18
19 int n,a[N],ad[N],b[N],len;
20 set<int> s[N];
21
22 IL void pre() {
23 len=1000;
24 for(R i=1;i<=n;++i) b[i]=(i-1)/len+1,s[b[i]].insert(a[i]);
25 }
26
27 IL void add(int l,int r,int c) {
28 for(R i=l;i<=min(r,b[l]*len);++i) {
29 s[b[i]].erase(a[i]);
30 a[i]+=c;
31 s[b[i]].insert(a[i]);
32 }
33 if(b[l]!=b[r])
34 for(R i=(b[r]-1)*len+1;i<=r;++i) {
35 s[b[i]].erase(a[i]);
36 a[i]+=c;
37 s[b[i]].insert(a[i]);
38 }
39 for(R i=b[l]+1;i<=b[r]-1;++i) ad[i]+=c;
40 }
41
42 IL void query(int l,int r,int x) {
43 int ans=-1;
44 for(R i=l;i<=min(r,b[l]*len);++i)
45 if(a[i]+ad[b[i]]<x) ans=max(ans,a[i]+ad[b[i]]);
46 if(b[l]!=b[r])
47 for(R i=(b[r]-1)*len+1;i<=r;++i)
48 if(a[i]+ad[b[i]]<x) ans=max(ans,a[i]+ad[b[i]]);
49 for(R i=b[l]+1;i<=b[r]-1;++i) {
50 set<int>::iterator it=s[i].lower_bound(x-ad[i]);
51 if(it==s[i].begin()) continue;
52 --it;ans=max(ans,*it+ad[i]);
53 }
54 printf("%d\n",ans);
55 }
56
57 int main() {
58 n=read();
59 for(R i=1;i<=n;++i) a[i]=read();
60 pre();
61 for(R i=1;i<=n;++i) {
62 int op=read(),l=read(),r=read(),c=read();
63 if(!op) add(l,r,c);
64 else query(l,r,c);
65 }
66 return 0;
67 }
区间加法,区间求和
1 #include<bits/stdc++.h>
2 #define int long long
3 #define IL inline
4 #define R register int
5 #define ls(x) a[x].ch[0]
6 #define rs(x) a[x].ch[1]
7 #define fa(x) a[x].fa
8
9 using namespace std;
10 const int N=1e5+5,inf=0x3f3f3f3f;
11
12 IL int read() {
13 int f=1;char ch;
14 while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
15 int res=ch-'0';
16 while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
17 return res*f;
18 }
19
20 int n,a[N],ad[N],b[N],len,sum[N];
21
22 IL void pre() {
23 len=sqrt(n);
24 for(R i=1;i<=n;++i) b[i]=(i-1)/len+1,sum[b[i]]+=a[i];
25 }
26
27 IL void add(int l,int r,int c) {
28 for(R i=l;i<=min(r,b[l]*len);++i)
29 a[i]+=c,sum[b[i]]+=c;
30 if(b[l]!=b[r])
31 for(R i=(b[r]-1)*len+1;i<=r;++i)
32 a[i]+=c,sum[b[i]]+=c;
33 for(R i=b[l]+1;i<=b[r]-1;++i) ad[i]+=c;
34 }
35
36 IL void query(int l,int r,int x) {
37 int ans=0;
38 for(R i=l;i<=min(r,b[l]*len);++i)
39 ans+=a[i]+ad[b[i]];
40 if(b[l]!=b[r])
41 for(R i=(b[r]-1)*len+1;i<=r;++i)
42 ans+=a[i]+ad[b[i]];
43 for(R i=b[l]+1;i<=b[r]-1;++i) {
44 ans+=sum[i]+ad[i]*len;
45 }
46 printf("%lld\n",ans%(x+1));
47 }
48
49 signed main() {
50 n=read();
51 for(R i=1;i<=n;++i) a[i]=read();
52 pre();
53 for(R i=1;i<=n;++i) {
54 int op=read(),l=read(),r=read(),c=read();
55 if(!op) add(l,r,c);
56 else query(l,r,c);
57 }
58 return 0;
59 }
区间开方,区间求和
//跳过已经不能再开方(元素值为0或1)的块
1 #include<bits/stdc++.h>
2 #define int long long
3 #define IL inline
4 #define R register int
5 #define ls(x) a[x].ch[0]
6 #define rs(x) a[x].ch[1]
7 #define fa(x) a[x].fa
8
9 using namespace std;
10 const int N=1e5+5,inf=0x3f3f3f3f;
11
12 IL int read() {
13 int f=1;char ch;
14 while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
15 int res=ch-'0';
16 while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
17 return res*f;
18 }
19
20 int n,a[N],b[N],len,sum[N],flag[N];
21
22 IL void pre() {
23 len=sqrt(n);
24 for(R i=1;i<=n;++i) b[i]=(i-1)/len+1,sum[b[i]]+=a[i];
25 }
26
27 IL void allsqrt(int x) {
28 if(flag[x]) return ;
29 flag[x]=1;
30 sum[x]=0;
31 for(R i=(x-1)*len+1;i<=x*len;++i) {
32 a[i]=sqrt(a[i]);sum[x]+=a[i];
33 if(a[i]>1) flag[x]=0;
34 }
35 }
36
37 IL void work(int l,int r,int c) {
38 for(R i=l;i<=min(r,b[l]*len);++i)
39 sum[b[i]]-=a[i],a[i]=sqrt(a[i]),sum[b[i]]+=a[i];
40 if(b[l]!=b[r])
41 for(R i=(b[r]-1)*len+1;i<=r;++i)
42 sum[b[i]]-=a[i],a[i]=sqrt(a[i]),sum[b[i]]+=a[i];
43 for(R i=b[l]+1;i<=b[r]-1;++i) allsqrt(i);
44 }
45
46 IL void query(int l,int r,int x) {
47 int ans=0;
48 for(R i=l;i<=min(r,b[l]*len);++i)
49 ans+=a[i];
50 if(b[l]!=b[r])
51 for(R i=(b[r]-1)*len+1;i<=r;++i)
52 ans+=a[i];
53 for(R i=b[l]+1;i<=b[r]-1;++i) {
54 ans+=sum[i];
55 }
56 printf("%lld\n",ans);
57 }
58
59 signed main() {
60 n=read();
61 for(R i=1;i<=n;++i) a[i]=read();
62 pre();
63 for(R i=1;i<=n;++i) {
64 int op=read(),l=read(),r=read(),c=read();
65 if(!op) work(l,r,c);
66 else query(l,r,c);
67 }
68 return 0;
69 }
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define fa(x) a[x].fa
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
IL int read() {
int f=1;char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,a[N],b[N],len,sum[N],flag[N];
IL void pre() {
len=sqrt(n);
for(R i=1;i<=n;++i) b[i]=(i-1)/len+1,sum[b[i]]+=a[i];
}
IL void allsqrt(int x) {
if(flag[x]) return ;
flag[x]=1;
sum[x]=0;
for(R i=(x-1)*len+1;i<=x*len;++i) {
a[i]=sqrt(a[i]);sum[x]+=a[i];
if(a[i]>1) flag[x]=0;
}
}
IL void work(int l,int r) {
for(R i=l;i<=min(r,b[l]*len);++i)
sum[b[i]]-=a[i],a[i]=sqrt(a[i]),sum[b[i]]+=a[i];
if(b[l]!=b[r])
for(R i=(b[r]-1)*len+1;i<=r;++i)
sum[b[i]]-=a[i],a[i]=sqrt(a[i]),sum[b[i]]+=a[i];
for(R i=b[l]+1;i<=b[r]-1;++i) allsqrt(i);
}
IL void query(int l,int r) {
int ans=0;
for(R i=l;i<=min(r,b[l]*len);++i)
ans+=a[i];
if(b[l]!=b[r])
for(R i=(b[r]-1)*len+1;i<=r;++i)
ans+=a[i];
for(R i=b[l]+1;i<=b[r]-1;++i) {
ans+=sum[i];
}
printf("%lld\n",ans);
}
signed main() {
n=read();
for(R i=1;i<=n;++i) a[i]=read();
int m=read();
pre();
for(R i=1;i<=m;++i) {
int op=read(),l=read(),r=read();
if(l>r) swap(l,r);
if(!op) work(l,r);
else query(l,r);
}
return 0;
}
单点插入,单点询问
//vector自带insert、重新分块(重构)
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
#define PII pair<int,int>
#define fi first
#define se second
#define mk make_pair
using namespace std;
const int N=5e5+5,inf=0x3f3f3f3f;
IL int read() {
int f=1;char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,a[N],len,st[N],m,b[N];
vector<int> s[N];
IL void pre() {
len=sqrt(n);m=n;
for(R i=1;i<=n;++i) b[i]=(i-1)/len+1,s[b[i]].push_back(a[i]);
}
IL PII find(int x) {
int i=1;
while(x>s[i].size()) x-=s[i].size(),i++;//x belongs to s[i]
return mk(i,x-1);
}
IL void rebuild() {
int top=0;
for(R i=1;i<=b[m];++i) {
for(R j=0;j<s[i].size();++j) st[++top]=s[i][j];
s[i].clear();
}
len=sqrt(n);
for(R i=1;i<=n;++i) b[i]=(i-1)/len+1,s[b[i]].push_back(st[i]);
}
IL void insert(int l,int r) {
PII t=find(l);
s[t.fi].insert(s[t.fi].begin()+t.se,r);
if(s[t.fi].size()>20*len) rebuild();
}
IL void query(int r) {
PII t=find(r);
printf("%lld\n",s[t.fi][t.se]);
}
signed main() {
m=n=read();
for(R i=1;i<=n;++i) a[i]=read();
pre();
for(R i=1;i<=m;++i) {
int op=read(),l=read(),r=read(),c=read();
if(!op) insert(l,r),++n;
else query(r);
}
return 0;
}
区间乘法,区间加法,单点询问
//先乘后加
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f,mod=10007;
IL int read() {
int f=1;
char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,a[N],b[N],len,ad[N],mul[N];
IL void pre() {
len=sqrt(n);
for(R i=1; i<=n; ++i) b[i]=(i-1)/len+1,mul[b[i]]=1;
}
void reset(int x) {
for(R i=(x-1)*len+1; i<=min(n,x*len); ++i)
a[i]=a[i]*mul[x]%mod,a[i]=(a[i]+ad[x])%mod;
mul[x]=1;ad[x]=0;
}
IL void work(int op,int l,int r,int c) {
reset(b[l]);
for(R i=l; i<=min(r,b[l]*len); ++i)
if(op) a[i]=a[i]*c%mod;
else a[i]=(a[i]+c)%mod;
if(b[l]!=b[r]) {
reset(b[r]);
for(R i=(b[r]-1)*len+1; i<=r; ++i)
if(op) a[i]=a[i]*c%mod;
else a[i]=(a[i]+c)%mod;
}
for(R i=b[l]+1; i<=b[r]-1; ++i)
if(op) mul[i]=mul[i]*c%mod,ad[i]=ad[i]*c%mod;
else ad[i]=(ad[i]+c)%mod;
}
IL void query(int i) {
int x=b[i];
//a[i]=a[i]*mul[x]%mod,a[i]=(a[i]+ad[x])%mod;
printf("%lld\n",(a[i]*mul[x]%mod+ad[x])%mod);
}
signed main() {
n=read();
for(R i=1; i<=n; ++i) a[i]=read();
pre();
for(R i=1; i<=n; ++i) {
int op=read(),l=read(),r=read(),c=read();
if(op==2) query(r);
else work(op,l,r,c);
}
return 0;
}
//线段树模板也可以用分块来做~吸个氧还是能卡过去的
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
IL int read() {
int f=1;
char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,a[N],b[N],len,ad[N],mul[N],m,p,sum[N];
IL int mod(int x) {return x>p?x-p:x;}
IL void pre() {
len=sqrt(n);
for(R i=1; i<=n; ++i) b[i]=(i-1)/len+1,mul[b[i]]=1,sum[b[i]]+=a[i];
}
void reset(int x) {
sum[x]=0;
for(R i=(x-1)*len+1; i<=min(n,x*len); ++i)
a[i]=(a[i]*mul[x]+ad[x])%p,sum[x]=mod(sum[x]+a[i]);
mul[x]=1;ad[x]=0;
}
IL void work(int op,int l,int r,int c) {
reset(b[l]);
for(R i=l; i<=min(r,b[l]*len); ++i)
if(op==1) sum[b[l]]+=(c-1)*a[i]%p,a[i]=a[i]*c%p;
else sum[b[l]]=mod(sum[b[l]]+c),a[i]=mod(a[i]+c);
if(b[l]!=b[r]) {
reset(b[r]);
for(R i=(b[r]-1)*len+1; i<=r; ++i)
if(op==1) sum[b[r]]+=(c-1)*a[i]%p,a[i]=a[i]*c%p;
else sum[b[r]]=mod(sum[b[r]]+c),a[i]=mod(a[i]+c);
}
for(R i=b[l]+1; i<=b[r]-1; ++i)
if(op==1) mul[i]=mul[i]*c%p,ad[i]=ad[i]*c%p;
else ad[i]=mod(ad[i]+c);
}
IL void query(int l,int r) {
int ans=0;
reset(b[l]);
for(R i=l; i<=min(r,b[l]*len); ++i) ans=mod(ans+a[i]);
if(b[l]!=b[r]) {
reset(b[r]);
for(R i=(b[r]-1)*len+1; i<=r; ++i) ans=mod(ans+a[i]);
}
for(R i=b[l]+1;i<=b[r]-1;++i) ans=mod(ans+mod(sum[i]*mul[i]%p+ad[i]*len%p));
printf("%lld\n",ans);
}
signed main() {
n=read(),m=read(),p=read();
for(R i=1; i<=n; ++i) a[i]=read();
pre();
for(R i=1; i<=m; ++i) {
int op=read(),l=read(),r=read();
if(op==3) query(l,r);
else {
int c=read();
work(op,l,r,c);
}
}
return 0;
}
区间询问等于一个数c的元素,并将这个区间的所有元素改为c
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
IL int read() {
int f=1;
char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,a[N],b[N],len,tag[N];
IL void pre() {
len=sqrt(n);
for(R i=1; i<=n; ++i) b[i]=(i-1)/len+1,tag[i]=-1;;
}
void reset(int x) {
if(tag[x]==-1) return ;
for(R i=(x-1)*len+1;i<=x*len;++i) a[i]=tag[x];
tag[x]=-1;
}
IL void query(int l,int r,int c) {
int ans=0;
reset(b[l]);
for(R i=l; i<=min(r,b[l]*len); ++i)
if(a[i]!=c) a[i]=c;
else ans++;
if(b[l]!=b[r]) {
reset(b[r]);
for(R i=(b[r]-1)*len+1; i<=r; ++i)
if(a[i]!=c) a[i]=c;
else ans++;
}
for(R i=b[l]+1;i<=b[r]-1;++i)
if(tag[i]==-1) {
for(R j=(i-1)*len+1;j<=i*len;++j)
if(a[j]!=c) a[j]=c;
else ans++;
tag[i]=c;
}
else {
if(tag[i]==c) ans+=len;
else tag[i]=c;
}
printf("%lld\n",ans);
}
signed main() {
n=read();
for(R i=1; i<=n; ++i) a[i]=read();
pre();
for(R i=1; i<=n; ++i) {
int l=read(),r=read(),c=read();
query(l,r,c);
}
return 0;
}
询问区间的最小众数
预处理保存以“段边界”为端点的区间[L,R]的众数。另外,对每个数值建立一个STL vector,按顺序保存该数值在序列a中每次出现的位置。
对于每个询问,扫描[l,L)与(R,r]中的每个数x,在对应的vector里二分查找即可得到x在[l,r]中出现的次数,从而更新答案。
——《算法竞赛进阶指南》
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
IL int read() {
int f=1;
char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,a[N],b[N],len,f[1505][1505],cnt[N],val[N],num;
map<int,int> m;
vector<int> pos[N];
IL void pre(int x) {
int mx=0,ans=0;
memset(cnt,0,sizeof(cnt));
for(R i=(x-1)*len+1; i<=n; ++i) {
cnt[a[i]]++;
if(cnt[a[i]]>mx||(cnt[a[i]]==mx&&val[a[i]]<val[ans])) mx=cnt[a[i]],ans=a[i];
f[x][b[i]]=ans;//分块间的最小众数
}
}
IL int find(int l,int r,int x) {
return upper_bound(pos[x].begin(),pos[x].end(),r)-lower_bound(pos[x].begin(),pos[x].end(),l);
}
IL void query(int l,int r) {
int ans=f[b[l]+1][b[r]-1];
int mx=find(l,r,ans);
for(R i=l; i<=min(r,b[l]*len); ++i) {
int tmp=find(l,r,a[i]);
if(tmp>mx||(tmp==mx&&val[a[i]]<val[ans])) mx=tmp,ans=a[i];
}
if(b[l]!=b[r])
for(R i=(b[r]-1)*len+1; i<=r; ++i) {
int tmp=find(l,r,a[i]);
if(tmp>mx||(tmp==mx&&val[a[i]]<val[ans])) mx=tmp,ans=a[i];
}
printf("%lld\n",val[ans]);
}
signed main() {
n=read();
for(R i=1; i<=n; ++i) {
a[i]=read();
if(!m[a[i]]) {
m[a[i]]=++num;
val[num]=a[i];
}
a[i]=m[a[i]];
pos[a[i]].push_back(i);
}
len=80;
for(R i=1; i<=n; ++i) b[i]=(i-1)/len+1;
for(R i=1; i<=b[n]; ++i) pre(i);
for(R i=1; i<=n; ++i) {
int l=read(),r=read();
if(l>r) swap(l,r);
query(l,r);
}
return 0;
}
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
IL int read() {
int f=1;
char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,a[N],b[N],len,f[1505][1505],cnt[N],val[N],num,lastans;
map<int,int> m;
vector<int> pos[N];
IL void pre(int x) {
int mx=0,ans=0;
memset(cnt,0,sizeof(cnt));
for(R i=(x-1)*len+1; i<=n; ++i) {
cnt[a[i]]++;
if(cnt[a[i]]>mx||(cnt[a[i]]==mx&&val[a[i]]<val[ans])) mx=cnt[a[i]],ans=a[i];
f[x][b[i]]=ans;//分块间的最小众数
}
}
IL int find(int l,int r,int x) {
return upper_bound(pos[x].begin(),pos[x].end(),r)-lower_bound(pos[x].begin(),pos[x].end(),l);
}
IL int query(int l,int r) {
int ans=f[b[l]+1][b[r]-1];
int mx=find(l,r,ans);
for(R i=l; i<=min(r,b[l]*len); ++i) {
int tmp=find(l,r,a[i]);
if(tmp>mx||(tmp==mx&&val[a[i]]<val[ans])) mx=tmp,ans=a[i];
}
if(b[l]!=b[r])
for(R i=(b[r]-1)*len+1; i<=r; ++i) {
int tmp=find(l,r,a[i]);
if(tmp>mx||(tmp==mx&&val[a[i]]<val[ans])) mx=tmp,ans=a[i];
}
return val[ans];
}
signed main() {
n=read();int M=read();
for(R i=1; i<=n; ++i) {
a[i]=read();
if(!m[a[i]]) {
m[a[i]]=++num;
val[num]=a[i];
}
a[i]=m[a[i]];
pos[a[i]].push_back(i);
}
len=80;
for(R i=1; i<=n; ++i) b[i]=(i-1)/len+1;
for(R i=1; i<=b[n]; ++i) pre(i);
for(R i=1; i<=M; ++i) {
int l=read(),r=read();
l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1;
if(l>r) swap(l,r);
lastans=query(l,r);
printf("%lld\n",lastans);
}
return 0;
}
和询问区间众数差不多。预处理出分块间正偶数的个数,查询时根据奇偶性具体判断即可。(在洛谷不开O(2)也能过
#include<bits/stdc++.h>
#define int long long
#define IL inline
#define R register int
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
IL int read() {
int f=1;
char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
int res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
return res*f;
}
int n,m,c,a[N],b[N],len,f[1505][1505],cnt[N],val[N],num,lastans,vis[N];
vector<int> pos[N];
IL void pre(int x) {
int tot=0;
for(R i=(x-1)*len+1; i<=n; ++i) cnt[a[i]]=0;
for(R i=(x-1)*len+1; i<=n; ++i) {
if(cnt[a[i]]!=0&&cnt[a[i]]%2==0) tot--;
cnt[a[i]]++;
if(cnt[a[i]]%2==0) tot++;
f[x][b[i]]=tot;
}
}
IL int find(int l,int r,int x) {
return upper_bound(pos[x].begin(),pos[x].end(),r)-lower_bound(pos[x].begin(),pos[x].end(),l);
}
IL int query(int l,int r) {
int ans;
if(b[l]==b[r]||b[l]+1==b[r]) {
ans=0;
for(R i=l; i<=r; ++i) {
if(vis[a[i]]) continue;
vis[a[i]]=1;
int tmp=find(l,r,a[i]);
if(tmp%2==0) ans++;
}
for(R i=l; i<=r; ++i) vis[a[i]]=0;
}
else{
ans=f[b[l]+1][b[r]-1];//b[l]+1~b[r]-1中的正偶数个数
int x=b[l]*len+1,y=(b[r]-1)*len;
for(R i=l; i<x; ++i) {
if(vis[a[i]]) continue;
vis[a[i]]=1;
int tmp=find(l,r,a[i]),bef=find(x,y,a[i]);
if(tmp%2==0) {
if(bef%2==1||bef==0) ans++;
} else if(bef&&(bef%2==0)) ans--;
}
for(R i=y+1; i<=r; ++i) {
if(vis[a[i]]) continue;
vis[a[i]]=1;
int tmp=find(l,r,a[i]),bef=find(x,y,a[i]);
if(tmp%2==0) {
if(bef%2==1||bef==0) ans++;
} else if(bef&&(bef%2==0)) ans--;
}
for(R i=l; i<x; ++i) vis[a[i]]=0;
for(R i=y+1; i<=r; ++i) vis[a[i]]=0;
}
return ans;
}
signed main() {
n=read();
c=read();
m=read();
len=sqrt((double)n/log((double)n)*log(2));
for(R i=1; i<=n; ++i) {
a[i]=read();
pos[a[i]].push_back(i);
b[i]=(i-1)/len+1;
}
for(R i=1; i<=b[n]; ++i) pre(i);
for(R i=1; i<=m; ++i) {
int l=read(),r=read();
l=(l+lastans)%n+1,r=(r+lastans)%n+1;
if(l>r) swap(l,r);
lastans=query(l,r);
printf("%lld\n",lastans);
}
return 0;
}