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;
}
posted @ 2023-11-01 15:00  Saka_Noa  阅读(12)  评论(0)    收藏  举报  来源