欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

洛谷P3245 [HNOI2016]大数(莫队)

程序员文章站 2022-12-15 18:16:19
题意 "题目链接" Sol 莫队板子题。。 维护出每个位置开始的字符串$mod P$的结果,记为$S_i$ 两个位置$l, r$满足条件当且仅当$S_l S_r = 0$,也就是$S_l = S_r$ 离散化之后直接上莫队就行了 对$2, 5$特判一下,因为2/5是10的因子,可能导致答案变大。直接 ......

题意

题目链接

sol

莫队板子题。。

维护出每个位置开始的字符串\(mod p\)的结果,记为\(s_i\)

两个位置\(l, r\)满足条件当且仅当\(s_l - s_r = 0\),也就是\(s_l = s_r\)

离散化之后直接上莫队就行了

\(2, 5\)特判一下,因为2/5是10的因子,可能导致答案变大。直接维护\(0/5\)的出现次数就可以了

考场上一高兴写了三个subtask。。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 + 10;
int mod;
template <typename a, typename b>
inline void mul2(a &x, b y) {
    x = 1ll * x * y % mod;
}
template <typename a, typename b>
inline int mul(a x, b y) {
    return 1ll * x * y % mod;
}
template <typename a, typename b>
inline int add(a x, b y) {
    return x + y >= mod ? x + y - mod : x + y;
}
inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    while (c < '0' || c > '9') {
        if (c == '-')
            f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int n, q, belong[maxn], block, l, r;
ll now, ans[maxn];
char s[maxn];

namespace sub3 {
int pro[maxn], num, date[maxn], cnt[maxn];
void des() {
    for (int i = 1; i <= n + 1; i++) date[++num] = pro[i];
    sort(date + 1, date + num + 1);
    num = unique(date + 1, date + num + 1) - date - 1;
    for (int i = 1; i <= n + 1; i++) pro[i] = lower_bound(date + 1, date + num + 1, pro[i]) - date;
}
struct query {
    int l, r, id;
    bool operator<(const query &rhs) const {
        return belong[l] == belong[rhs.l] ? r < rhs.r : belong[l] < belong[rhs.l];
    }
} q[maxn];
void add(int x) {
    now += cnt[x];
    cnt[x]++;
}
void delet(int x) {
    cnt[x]--;
    now -= cnt[x];
}
void solve() {
    block = sqrt(n);
    for (int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1;
    for (int i = n, base = 1; i >= 1; i--, mul2(base, 10)) pro[i] = add(pro[i + 1], mul((s[i] - '0'), base));
    des();
    q = read();
    for (int i = 1; i <= q; i++) q[i].l = read(), q[i].r = read() + 1, q[i].id = i;
    sort(q + 1, q + q + 1);
    l = 1, r = 0;
    for (int i = 1; i <= q; i++) {
        while (r < q[i].r) add(pro[++r]);
        while (r > q[i].r) delet(pro[r--]);
        while (l < q[i].l) delet(pro[l++]);
        while (l > q[i].l) add(pro[--l]);
        ans[q[i].id] = now;
    }
    for (int i = 1; i <= q; i++) cout << ans[i] << '\n';
}
}  // namespace sub3

namespace sub1 {
int cnt[maxn], a[maxn];
struct query {
    int l, r, id;
    bool operator<(const query &rhs) const {
        return belong[l] == belong[rhs.l] ? r < rhs.r : belong[l] < belong[rhs.l];
    }
} q[maxn];
void add(int x, int opt) {
    if (opt) {
        if (x == 0)
            now += r - l + 1;
    } else {
        now += cnt[0];
    }
    cnt[x]++;
}
void delet(int x, int opt) {
    cnt[x]--;
    if (opt) {
        if (x == 0)
            now -= r - l + 1;
    } else {
        now -= cnt[0];
    }
}
void solve() {
    block = sqrt(n);
    for (int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1, a[i] = (s[i] - '0') % 2;
    q = read();
    for (int i = 1; i <= q; i++) q[i].l = read(), q[i].r = read(), q[i].id = i;
    sort(q + 1, q + q + 1);
    l = 1, r = 0;
    for (int i = 1; i <= q; i++) {
        while (r < q[i].r) add(a[++r], 1);
        while (r > q[i].r) delet(a[r--], 1);
        while (l < q[i].l) delet(a[l++], 0);
        while (l > q[i].l) add(a[--l], 0);
        ans[q[i].id] = now;
    }
    for (int i = 1; i <= q; i++) cout << ans[i] << '\n';
}
}

namespace sub2 {
int cnt[maxn], a[maxn], len[maxn];
struct query {
    int l, r, id;
    bool operator < (const query &rhs) const {
        return belong[l] == belong[rhs.l] ? r < rhs.r : belong[l] < belong[rhs.l];
    }
}q[maxn];
void add(int x, int opt, int pos) {
    cnt[x]++;
    if(opt) {
        if(x == 0 || x == 5) now += r - l + 1;
    } else {
        now += cnt[0] + cnt[5];
    }
    
}
void delet(int x, int opt, int pos) {
    if(opt) {
        if(x == 0 || x == 5) now -= r - l + 1;
    } else {
        now -= cnt[0] + cnt[5];
    }
    cnt[x]--;
}
void solve() { 
    block = sqrt(n);
    for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1, a[i] = s[i] - '0';
    q = read();
    for(int i = 1; i <= q; i++) q[i].l = read(), q[i].r = read(), q[i].id = i;
    sort(q + 1, q + q + 1);
    l = 1, r = 0;
    for(int i = 1; i <= q; i++) {   
        while(l > q[i].l) 
            --l, add(a[l], 0, l);
        while(r > q[i].r) 
            delet(a[r], 1, r), r--;
        while(l < q[i].l) 
            delet(a[l], 0, l), l++;
        while(r < q[i].r) 
            ++r, add(a[r], 1, r);
        ans[q[i].id] = now;
    }
    for(int i = 1; i <= q; i++) cout << ans[i] << '\n';
}

}

int main() {
    mod = read();
    scanf("%s", s + 1);
    n = strlen(s + 1);
    if (mod == 2)
        sub1::solve();
    else if (mod == 5)
        sub2::solve();
    else
        sub3::solve();
    return 0;
}
/*
11
1211
1
1 4
*/