站外题求卡常

学术版

喵仔牛奶 @ 2022-08-04 18:34:45

给定两个长度为 N 的序列 AB,现在有 Q 个询问,每个询问给出两个数字 XY, 你需要回答 A 序列前 X 个元素构成的集合跟 B 序列前 Y 个元素构成的集合是否相同,相同输出 Yes, 否则输出 No,每个询问占一行。(集合指去重后的元素集合即 <set>)

1\leq N,Q\leq2\times10^5

模拟赛题,赛时我写了莫队,忘记离散化炸了,赛后写了正解,可是莫队死活过不去,时间复杂度 O(n\sqrt m) 正确的。

#pragma GCC optimize("Ofast")
#pragma GCC optimize(1, 2, 3, "inline")
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
using namespace std;
typedef long long ll;
const int N = 4e5 + 5;
struct opt {
    int l, r, id;
} s[N];
ll a[N], c[N], ans[N], pos[N], cnt1[N], cnt2[N], t[N], slen, sum, cnt, siz, n, m, l, r;
bool w[N];
inline bool cmp(opt x, opt y) {
    if (pos[x.l] != pos[y.l]) return x.l < y.l;
    return (pos[x.l] & 1) ? x.r < y.r : x.r > y.r;
}
inline void push(int x) {
    if (!w[x]) w[x] = true, siz ++;
    else w[x] = false, siz --;
}
inline int read() {
    register int t = 1, a = 0;
    register char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') t = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0')
        a = a * 10 + ch - '0', ch = getchar();
    return a * t;
}
inline void write(long long x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
void init() {
    n = read(), slen = n / sqrt(n);
    for (int i = 1; i <= n; i ++)
        a[i] = read(), t[++ cnt] = a[i];
    for (int i = 1; i <= n; i ++)
        c[i] = read(), t[++ cnt] = c[i];
    m = read();
    for (int i = 1; i <= n; i ++)
        pos[i] = (i - 1) / slen + 1;
    sort(t + 1, t + 1 + cnt);
    sum = unique(t + 1, t + 1 + cnt) - t - 1;
    for (int i = 1; i <= n; i ++)
        a[i] = lower_bound(t + 1, t + 1 + sum, a[i]) - t;
    for (int i = 1; i <= n; i ++)
        c[i] = lower_bound(t + 1, t + 1 + sum, c[i]) - t;
}
int main() {
    init();
    for (int i = 1; i <= m; i ++)
        s[i].l = read(), s[i].r = read(), s[i].id = i;
    sort(s + 1, s + 1 + m, cmp);
    for (int i = 1; i <= m; i ++) {
        while (l > s[i].l) if (!(-- cnt1[a[l --]])) push(a[l + 1]);
        while (l < s[i].l) if (!(cnt1[a[++ l]] ++)) push(a[l]);
        while (r > s[i].r) if (!(-- cnt2[c[r --]])) push(c[r + 1]);
        while (r < s[i].r) if (!(cnt2[c[++ r]] ++)) push(c[r]);
        ans[s[i].id] = !siz;
    }
    for (int i = 1; i <= m; i ++)
        puts(ans[i] ? "Yes" : "No");
    return 0;
}

by A_zjzj @ 2022-08-04 18:39:56

貌似可以用哈希做到nlogn?


by 喵仔牛奶 @ 2022-08-04 18:40:54

@A_zjzj 对啊,正解我知道,我已经A了,我就是想让莫队过qwq


by 红黑树 @ 2022-08-04 18:42:33

你现在几秒?时限几秒?


by 王熙文 @ 2022-08-04 18:44:14

at 原题 某次 abc 的 e


by 喵仔牛奶 @ 2022-08-04 18:44:32

@红黑树 时限1s,现在有两个点1100ms以上,剩下的在200ms以下。

老师没有讲过莫队,应该不会故意卡莫队。


by 喵仔牛奶 @ 2022-08-04 18:48:50

@王熙文 有题号吗qwq


by TLEWA @ 2022-08-04 22:22:36

@喵仔牛奶 循环展开+手动O3(如果可以的话)


by TLEWA @ 2022-08-04 22:24:24

@喵仔牛奶 bool数组改bitset(不开O2情况下就算了,不开O2时这玩意还跑不过bool数组)


by TLEWA @ 2022-08-04 22:26:25

az,开了O2啊,火车头走起~


by TLEWA @ 2022-08-04 22:28:43

@喵仔牛奶 火车头

然后自己调,有时全加是负优化...


| 下一页