JZOJ4417 【HNOI2016模拟4.1】神奇的字符串 线段树维护信息

题目大意

给定5个参数,分别为 N,A,B,P,M 其中我们可以生成字符串 c 中的第 i ci=[(Ai+B)modNB] ,下标为 0 ~ N1 ,并且这个字符串是循环的。现在给你另一个 M 为的字符串 S ,现在有 Q 组操作,有两种:每种都给定一个 p
1. 询问 c 的第 p 位开始往取 M 位得到的字符串与 S 有多少位不同。
2. 将 S 的第 p 为取反。

N109
1A,B,P,MN
1N,Q105

解题思路

如果我们直接拿生成的字符串去做,那么这个是很难维护了,那么我们考虑把 (Ai+B)modN 相同的分成一类。我们考虑 c 中的哪些字符串的第 i 位于 Si 不相等。根据上面那条式子,移一下项。如果我们把按 (Ai+B)modN 为下标的话,那么对应的位置肯定是连续一段的,那么我们就可以用线段树来维护一段区间覆盖的点。最后的答案就是 (Acp+B)modN 被覆盖了多少次。

程序

//YxuanwKeith
#include 
#include 
#include 

using namespace std;

const int MAXN = 1e5 + 5;

struct Node {
    int l, r, Num;
} Tr[MAXN * 50];

int tot, Q, N, A, B, P, M, Root;
char S[MAXN], C[10];

int Calc(int i) {
    return (1ll * i * A + B) % N;
}

int Query(int Now, int l, int r, int Side) {
    if (!Now) return 0;
    if (l == r) return Tr[Now].Num;
    int Mid = (l + r) >> 1;
    if (Side <= Mid) return Tr[Now].Num + Query(Tr[Now].l, l, Mid, Side); else
        return Tr[Now].Num + Query(Tr[Now].r, Mid + 1, r, Side);
}

void Modify(int &Now, int l, int r, int lx, int rx, int val) {
    if (rx < l || lx > r) return;
    if (!Now) Now = ++ tot;
    if (l >= lx && r <= rx) {
        Tr[Now].Num += val;
        return;
    }
    int Mid = (l + r) >> 1;
    Modify(Tr[Now].l, l, Mid, lx, rx, val), Modify(Tr[Now].r, Mid + 1, r, lx, rx, val);
}

void Modify(int v, int val) {
    int c = S[v] - '0', l, r;
    if (c == 0) l = 0, r = P - 1; else l = P, r = N - 1;
    l = ((l % N - 1ll * A * v % N) % N + N) % N;
    r = ((r % N - 1ll * A * v % N) % N + N) % N;
    if (l <= r) Modify(Root, 0, N - 1, l, r, val); else
        Modify(Root, 0, N - 1, l, N - 1, val), Modify(Root, 0, N - 1, 0, r, val); 
} 

int main() {
    scanf("%d%d%d%d%d\n", &N, &A, &B, &P, &M);
    scanf("%s", S);
    Root = tot = 1;
    for (int i = 0; i < M; i ++) Modify(i, 1);
    scanf("%d", &Q);
    for (int i = 1; i <= Q; i ++) {
        int v;
        scanf("\n%s%d", C + 1, &v);
        if (C[1] == 'Q') printf("%d\n", M - Query(Root, 0, N - 1, Calc(v))); else {
            Modify(v, -1);
            S[v] = (S[v] == '0') ? '1' : '0';
            Modify(v, 1);
        }
    }
}

你可能感兴趣的:(算法-数据结构)