前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >洛谷P3245 [HNOI2016]大数(莫队)

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

作者头像
attack
发布2019-03-15 16:08:57
3180
发布2019-03-15 16:08:57
举报

题意

题目链接

Sol

莫队板子题。。

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

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

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

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

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

代码语言:javascript
复制
#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
*/
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-03-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题意
  • Sol
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档