今天看到一道题,有1e6个数,2e7个询问,每个询问给出区间[l,r],对每个询问输出区间内的数的乘积mod p,由于时间限制很紧,每个询问基本要O(1)回答,然后我了解到这个数据结构可以解决这类问题,下面是求和的模板。0 indexed
# include <bits/stdc++.h>
using namespace std;
const int N = 1058576, LOGN = 22;
long long v[N][LOGN];
long long a[N], n, q;
void build(int i, int s, int e){
if(s == e) return;
int m = (s + e)/2;
v[m][i] = a[m];
for(int j = m-1; j >= s; j--){
v[j][i] = v[j+1][i]+a[j];//改成乘号就是区间乘积
}
if(m + 1 <= e){
v[m+1][i] = a[m+1];
for(int j = m+2; j <= e; j++){
v[j][i] = v[j-1][i]+a[j];//改成乘号就是区间乘积
}
}
build(i+1, s, m);
build(i+1, m+1, e);
}
int main()
{
scanf("%d%d",&n,&q);//n个数,q个询问
int LEV = __builtin_clz(n);
int size = 1<<(31-LEV);
if(n != size)LEV--, size *= 2;
for(int i=0; i<n; ++i) scanf("%d",&a[i]);
build(0,0,size-1);
int q;
while(q--)
{
int l, r;
scanf("%d%d",&l,&r);
--l;--r;
if(l==r)
{
printf("%d\n",a[l]);
continue;
}
unsigned int temp = __builtin_clz(l^r);
unsigned int lev = temp-LEV-1;
int ans = v[r][lev]+v[l][lev];
printf("%d\n",ans);
}
return 0;
}