P8421 rsraogps
已知$$M_{l,r} = \bigwedge_{i=l}^{r} a_i \times \bigvee_{i=l}^{r}b_i \times \gcd_{i = l}^{r} c_i$$
对于每个询问 $l,r$ 求$$\sum_{p=l}^{r} \sum_{q=p}^{r} M_{p,q}$$
实际上,我们可以将式子改写成:$$\sum_{i = l}^{r} \sum_{j = i}^{r} M_{j,r}$$
可以使用扫描线维护。
具体的维护 $S = \sum_{i = 1}^{r} \sum_{j = i}^{r} M_{j,r}$,每个询问答案为 $S_r - S_{l - 1}$。
当加入一个数时,最多有 $O(\log V)$ 个位置受影响,我们每次暴力维护即可,复杂度 $O(n \log V + m)$
#include<bits/stdc++.h>
typedef unsigned int i32;
using namespace std;
#define gc getchar
const int N = 1e6 + 500;
const int Q = 5e6 + 500;
int read() {
int x = 0; char c = gc();
while(!isdigit(c)) c = gc();
while(isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = gc();
return x;
}
struct node {int l, r, id; };
struct G{ i32 a, b, c; };
struct E{ i32 s; int t; };
int n, m, T;
i32 S[N], ans[Q];
E Ps[N];
G M[N];
vector< node > Qr[N];
i32 gcd(i32 a, i32 b) {
return b ? gcd(b, a % b) : a;
}
G operator + (G a, G b) {
a.a &= b.a;
a.b |= b.b;
a.c = gcd(a.c, b.c);
return a;
}
bool operator == (G a, G b) {
return a.a == b.a && a.b == b.b && a.c == b.c;
}
i32 _Q(int l) { return S[l] + Ps[l].s * (T - Ps[l].t); }
i32 _Q(int l, int r) { return _Q(r) - _Q(l - 1); }
void o_ut() {
for(int i = 1;i <= n; ++i) cerr << _Q(i) << " ";
cerr << endl;
for(int i = 1; i <= n; ++i) cerr << Ps[i].s << " " << Ps[i].t << "\n";
cerr << endl;
cerr << endl;
}
int main(){
n = read();
m = read();
for(int i = 1; i <= n; ++i) M[i].a = read();
for(int i = 1; i <= n; ++i) M[i].b = read();
for(int i = 1; i <= n; ++i) M[i].c = read();
for(int i = 1;i <= m; ++i) {
int l, r;
l = read(), r = read();
Qr[r].emplace_back(node{l, r, i});
}
for(int i = 1; i <= n; ++i){
int R = i - 1;
while(R) {
G P = M[R] + M[R + 1];
if(P == M[R]) break;
M[R] = P;
--R;
}
S[i] = _Q(i - 1);
for(int t = R; t <= i; ++t) {
S[t] = _Q(t);
Ps[t].s = Ps[t - 1].s + M[t].a * M[t].b * M[t].c;
Ps[t].t = T;
}
++T;
//o_ut();
for(auto o : Qr[i]) ans[o.id] = _Q(o.l, i);
}
for(int i = 1;i <= m; ++i) printf("%u\n", ans[i]);
return 0;
}

浙公网安备 33010602011771号