社区讨论

带修莫队常数一般是多少?

P4690[Ynoi Easy Round 2016] 镜中的昆虫参与者 2已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@lo1be66m
此快照首次捕获于
2023/10/22 18:17
2 年前
此快照最后确认于
2023/11/02 18:37
2 年前
查看原帖
rt,我算出来 (105)53(10^5)^{\frac{5}{3}} 也就是 2e8,开两秒按道理应该完全能过啊!
然后有人模拟赛放了这题,我写了 暴力+带修莫队+珂朵莉树拿 80 分,这是我的代码:
CPP
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;

inline int read() {
    char c; bool f = true;
    while (!isdigit(c = getchar())) f = c != '-';
    int x = c ^ 48;
    while (isdigit(c = getchar())) x = x * 10 + (c ^ 48);
    return f ? x : -x;
}

const int N = 500010;
const int p = 1000000007;

int n, m, a[N];
struct input {
    int op, l, r, x, ans, id;
} in[N];

namespace subtask1 {
    inline int main() {
        for (int i = 1; i <= m; i++) {
            if (in[i].op == 1) {
                for (int j = in[i].l; j <= in[i].r; j++) {
                    a[j] = in[i].x;
                }
            } else {
                unordered_set<int> s;
                for (int j = in[i].l; j <= in[i].r; j++) {
                    s.insert(a[j]);
                }
                printf("%d\n", s.size());
            }
        }
        return 0;
    }
}

namespace subtask2 {
    int bel[N];
    struct query {
        int l, r, t, id;
        inline bool operator < (const query &x) const {
            if (bel[l] == bel[x.l]) {
                if (bel[r] == bel[x.r]) {
                    return (bel[r] & 1) ? (t < x.t) : (t > x.t);
                } else {
                    return (bel[l] & 1) ? (bel[l] < bel[x.l]) : (bel[l] > bel[x.l]);
                }
            } else {
                return bel[l] < bel[x.l];
            }
        }
    } q[N];

    int tot, qn, pos[N], u[N], v[N];
    int cnt[N], cur;

    inline void insert(int x) {
        // cout << "insert: " << x << endl;
        cnt[x]++;
        if (cnt[x] == 1) {
            cur++;
        }
    }

    inline void remove(int x) {
        // cout << "remove: " << x << endl;
        cnt[x]--;
        if (cnt[x] == 0) {
            cur--;
        }
    }

    int qans[N];

    inline int main() {
        int t = pow(m, 0.67);
        for (int i = 1; i <= m; i++) {
            bel[i] = i / t + 1;
        }
        for (int i = 1; i <= m; i++) {
            if (in[i].op == 1) {
                tot++;
                u[tot] = a[in[i].l];
                a[in[i].l] = in[i].x;
                v[tot] = a[in[i].l];
                pos[tot] = in[i].l;
                // cout << "mdf #" << tot << " " << u[tot] << " -> " << v[tot] << endl;
            } else {
                qn++;
                q[qn].l = in[i].l;
                q[qn].r = in[i].r;
                q[qn].id = qn;
                q[qn].t = tot;
            }
        }
        sort(q + 1, q + qn + 1);
        int l = 1, r = 0, now = tot;
        for (int i = 1; i <= qn; i++) {
            // cout << "query: " << q[i].id << " " << q[i].l << " " << q[i].r << " " << q[i].t << " - " << " " << l << " " << r << " " << now << endl;
            while (r < q[i].r) insert(a[++r]);
            while (l > q[i].l) insert(a[--l]);
            while (r > q[i].r) remove(a[r--]);
            while (l < q[i].l) remove(a[l++]);
            // cout << "query " << q[i].id << " I'm here: " << l << " " << r << endl;
            while (now < q[i].t) {
                now++;
                assert(a[pos[now]] == u[now]);
                if (l <= pos[now] && pos[now] <= r) {
                    remove(a[pos[now]]);
                }
                a[pos[now]] = v[now];
                if (l <= pos[now] && pos[now] <= r) {
                    insert(a[pos[now]]);
                }
            }
            while (now > q[i].t) {
                // cout << "processing modification: " << pos[now] << " " << u[now] << " " << v[now] << endl;
                assert(a[pos[now]] == v[now]);
                if (l <= pos[now] && pos[now] <= r) {
                    remove(a[pos[now]]);
                }
                a[pos[now]] = u[now];
                if (l <= pos[now] && pos[now] <= r) {
                    insert(a[pos[now]]);
                }
                now--;
            }
            qans[q[i].id] = cur;
        }
        for (int i = 1; i <= qn; i++) {
            printf("%d\n", qans[i]);
        }

        return 0;
    }
}

namespace subtask3 {
    struct segment {
        int l, r, v;
        inline bool operator < (const segment &x) const {
            if (l == x.l) {
                return r < x.r;
            }
            return l < x.l;
        }
        inline segment(int l, int r, int v): l(l), r(r), v(v) {}
    };

    set<segment> s;

    typedef set<segment>::iterator it;

    inline it split(int v) {
        if (v > n) return s.end();
        // [..., x - 1], [x, ...]
        it x = s.lower_bound(segment(v, 0, 0));
        if (x == s.end() || x -> l > v) {
            x--;
            assert(x -> l < v);
            segment sg = *x;
            s.erase(x);
            s.insert(segment(sg.l, v - 1, sg.v));
            return s.insert(segment(v, sg.r, sg.v)).first;
        } else {
            if (x -> l == x -> r) {
                assert(x -> l == v);
                return x;
            } else {
                return x;
                // segment sg = *x;
                // s.erase(x);

                // s.insert(segment(sg.l, v - 1, sg.v));
                // return s.insert(segment(v, sg.r, sg.v)).first;
            }
        }
    }

    inline void spread(it x) {
        segment sg = *x;
        bool success = false;
        if (x != s.begin()) {
            it pre = x;
            --pre;
            if (pre -> v == x -> v) {
                sg.l = pre -> l;
                s.erase(pre);
                success = true;
            }
        }
        if (x != --s.end()) {
            it nxt = x;
            ++nxt;
            if (nxt -> v == x -> v) {
                sg.r = nxt -> r;
                s.erase(nxt);
                success = true;
            }
        }
        if (success) {
            s.erase(x);
            s.insert(sg);
        }
    }

    inline void assign(int L, int R, int v) {
        it r = split(R + 1), l = split(L);
        // cout << "assign: " << L << " " << R << " " << v << " " << (l == r) << endl;
        while (l != r) {
            // cout << "l: [" << (l -> l) << ", " << (l -> r) << "], r: [" << (r -> l) << ", " << (r -> r) << "]" << endl;
            // s.erase(l);
            it cpy = l;
            l++;
            s.erase(cpy);
        }
        // exit(0);
        spread(s.insert(segment(L, R, v)).first);
    }

    inline int query(int L, int R) {
        unordered_set<int> s;
        it r = split(R + 1), l = split(L);
        while (l != r) {
            s.insert(l -> v);
            l++;
        }
        return s.size();
    }

    inline void print() {
        for (it i = s.begin(); i != s.end(); i++) {
            printf("[%d, %d]: %d, ", i -> l, i -> r, i -> v);
        }
        puts("");
    }

    inline int main() {
        for (int i = 1; i <= n; i++) {
            spread(s.insert(segment(i, i, a[i])).first);
        }
        for (int i = 1; i <= m; i++) {
            // cout << "op #" << i << endl;
            // print();
            if (in[i].op == 1) {
                assign(in[i].l, in[i].r, in[i].x);
            } else {
                printf("%d\n", query(in[i].l, in[i].r));
            }
        }
        return 0;
    }
}

vector<int> v;

int main() {
    // freopen("D.in", "r", stdin);
    // freopen("D.out", "w", stdout);
    
    n = read(); m = read();
    for (int i = 1; i <= n; i++) {
        a[i] = read();
        v.push_back(a[i]);
    }
    bool toggle1 = true;
    for (int i = 1; i <= m; i++) {
        in[i].op = read();
        if (in[i].op == 1) {
            in[i].l = read();
            in[i].r = read();
            in[i].x = read();
            v.push_back(in[i].x);
            toggle1 &= (in[i].l == in[i].r);
        } else {
            in[i].l = read();
            in[i].r = read();
        }
    }
    sort(v.begin(), v.end());
    for (int i = 1; i <= n; i++) {
        a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    }
    for (int i = 1; i <= m; i++) {
        if (in[i].op == 1) {
            in[i].x = lower_bound(v.begin(), v.end(), in[i].x) - v.begin() + 1;
        }
    }
    // bool debug = true;
    bool debug = false;
    if (n <= 1000 && m <= 1000 && !debug) {
        return subtask1::main();
    } else if (toggle1) {
        return subtask2::main();
    } else {
        // cerr << "sb" << endl;
        return subtask3::main();
    }
}
/*

10 10
9 9 0 9 8 7 10 8 6 7 
1 6 8 4
1 1 1 1
1 3 10 2
1 2 3 0
2 1 3
2 1 8
2 6 6
1 1 2 0
1 8 9 7
2 6 7

10 10
6 0 9 7 5 7 4 5 10 6 
2 9 10
2 1 3
1 2 5 4
2 3 3
2 1 10
2 3 7
1 1 10 7
2 4 9
1 1 6 5
2 7 9

2
3
1
5
2
1
1

5 5
1 2 3 4 5
2 1 3
2 2 5
1 4 4 3
2 2 5
2 4 5

3
4
3
2
1 2 3 3 5

10 10
315300 924016 265298 633282 540235 874286 367789 74037 87457 345556
1 5 5 934930
1 5 5 502435
1 5 5 144462
2 4 5
2 1 8
2 7 8
2 3 6
1 10 10 5819
1 2 2 480922
2 9 10

5 5 
1 2 3 4 5 
2 1 5 
1 2 3 4 
2 1 5 
2 3 3 
2 2 4

2
8
2
4
2

20 20
4 1 2 0 2 4 3 0 1 4 1 1 4 1 4 1 2 1 2 1
1 2 2 0
1 3 3 3
1 4 4 2
2 1 1
2 2 5
1 1 1 1
1 3 3 3
1 1 1 4
2 1 3
2 1 5
1 2 2 4
2 1 3
2 1 4
1 2 2 0
2 1 2
1 3 3 2
1 1 1 3
2 1 3
1 1 1 2
1 3 3 3

1
3
3
4
2
3
2
3

10 2
6 7 10 1 1 1 1 0 4 8
1 9 2 5
2 3 6
*/
只看 subtask2(莫队)部分就行,是我复杂度写假了还是带修莫队常数大?

回复

4 条回复,欢迎继续交流。

正在加载回复...