QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#71807#2585. 原题识别He_Ren100 ✓1148ms31252kbC++2310.5kb2023-01-12 01:20:072023-01-12 01:21:57

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-01-12 01:21:57]
  • 评测
  • 测评结果:100
  • 用时:1148ms
  • 内存:31252kb
  • [2023-01-12 01:20:07]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 5;
const int MAXM = 2e5 + 5;

inline int read(void) {
    int res = 0;
    char c = getchar();

    while (c < '0' || c > '9')
        c = getchar();

    while (c >= '0' && c <= '9')
        res = res * 10 + c - '0', c = getchar();

    return res;
}

namespace Gen {
unsigned int SA, SB, SC;
unsigned int Rand(void) {
    SA ^= SA << 16;
    SA ^= SA >> 5;
    SA ^= SA << 1;
    unsigned int t = SA;
    SA = SB;
    SB = SC;
    SC ^= t ^ SA;
    return SC;
}
}

struct Segment_Tree {
    ll sum[MAXN << 2], tag[MAXN << 2];
#define ls(u) ((u)<<1)
#define rs(u) ((u)<<1|1)
#define lson(u) ls(u),l,mid
#define rson(u) rs(u),mid+1,r
    inline void push_up(int u) {
        sum[u] = sum[ls(u)] + sum[rs(u)];
    }
    inline void upd(int u, ll k, int len) {
        sum[u] += len * k;
        tag[u] += k;
    }
    inline void push_down(int u, int len) {
        if (tag[u]) {
            upd(ls(u), tag[u], (len + 1) >> 1);
            upd(rs(u), tag[u], len >> 1);
            tag[u] = 0;
        }
    }
    void build(int u, int l, int r) {
        sum[u] = tag[u] = 0;

        if (l == r)
            return;

        int mid = (l + r) >> 1;
        build(lson(u));
        build(rson(u));
    }
    void add(int u, int l, int r, int ql, int qr, ll k) {
        if (ql <= l && r <= qr) {
            upd(u, k, r - l + 1);
            return;
        }

        push_down(u, r - l + 1);
        int mid = (l + r) >> 1;

        if (ql <= mid)
            add(lson(u), ql, qr, k);

        if (mid < qr)
            add(rson(u), ql, qr, k);

        push_up(u);
    }
    ll getsum(int u, int l, int r, int ql, int qr) {
        if (ql <= l && r <= qr)
            return sum[u];

        push_down(u, r - l + 1);
        int mid = (l + r) >> 1;

        if (ql <= mid && mid < qr)
            return getsum(lson(u), ql, qr) + getsum(rson(u), ql, qr);
        else
            return ql <= mid ? getsum(lson(u), ql, qr) : getsum(rson(u), ql, qr);
    }

    int n;
    inline void build(int _n) {
        n = _n;
        build(1, 1, n);
    }
    inline void add(int ql, int qr, ll k) {
        if (ql <= qr)
            add(1, 1, n, ql, qr, k);
    }
    inline ll getsum(int ql, int qr) {
        return ql <= qr ? getsum(1, 1, n, ql, qr) : 0;
    }
};

struct Query {
    int type, u, v;
    Query(void) {}
    Query(int _type, int _u, int _v): type(_type), u(_u), v(_v) {}
};

int anc[MAXN], a[MAXN], pos[MAXN];
Query qs[MAXM];
ll res[MAXM];

void solve(void) {
    int n = read(), d = read();
    Gen::SA = read();
    Gen::SB = read();
    Gen::SC = read();

    for (int i = 2; i <= d; ++i)
        anc[i] = i - 1;

    for (int i = d + 1; i <= n; ++i)
        anc[i] = Gen::Rand() % (i - 1) + 1;

    for (int i = 1; i <= n; ++i)
        a[i] = Gen::Rand() % n + 1;

    //  printf("n = %d, d = %d\n",n,d);
    //  for(int i=1; i<=n; ++i) printf("anc[%d] = %d,\ta[%d] = %d\n",i,anc[i],i,a[i]);

    for (int i = 1; i <= d; ++i)
        pos[i] = i;

    for (int i = d + 1; i <= n; ++i)
        pos[i] = pos[anc[i]];

    static int dep[MAXN];

    for (int i = 1; i <= d; ++i)
        dep[i] = 0;

    for (int i = d + 1; i <= n; ++i)
        dep[i] = dep[anc[i]] + 1;

    auto lca = [&](int u, int v) {
        while (dep[u] > dep[v])
            u = anc[u];

        while (dep[v] > dep[u])
            v = anc[v];

        while (u != v)
            u = anc[u], v = anc[v];

        return u;
    };

    static vector<int> qid[MAXN];

    for (int i = 1; i <= d; ++i)
        qid[i].clear();

    int m = read();

    for (int i = 1; i <= m; ++i) {
        int type = read(), u = read(), v = read();

        if (pos[u] > pos[v])
            swap(u, v);

        qs[i] = Query(type, u, v);
        qid[pos[v]].push_back(i);
    }

    memset(res, 0, (m + 1) << 3);

    static int nxt[MAXN], lst[MAXN];
    fill(lst + 1, lst + n + 1, d + 1);

    for (int i = d; i >= 1; --i)
        nxt[i] = lst[a[i]], lst[a[i]] = i;

    static vector<int> occ[MAXN];

    for (int i = 1; i <= n; ++i)
        occ[i] = {0};

    for (int i = 1; i <= d; ++i)
        occ[a[i]].push_back(i);

    for (int i = 1; i <= n; ++i)
        occ[i].push_back(d + 1);

    static Segment_Tree sumk, sumb;
    sumk.build(d);
    sumb.build(d);

    for (int i = 1; i <= n; ++i)
        sumk.add(lst[i], d, 1);

    fill(lst + 1, lst + n + 1, 0);

    for (int RR = 1; RR <= d; ++RR) {
        sumk.add(lst[a[RR]] + 1, RR - 1, 1);
        sumb.add(lst[a[RR]] + 1, RR - 1, -RR + 1);
        lst[a[RR]] = RR;

        for (int i : qid[RR]) {
            int type = qs[i].type, u = qs[i].u, v = qs[i].v;
            int l = pos[u], r = pos[v];

            static int bak[MAXN], sta[MAXN], cnt = 0, tp = 0;
            auto pushbak = [&](int x) {
                if (++bak[x] == 1)
                    ++cnt;

                sta[++tp] = x;
            };
            auto roll = [&](int save) {
                while (tp > save)
                    if (--bak[sta[tp--]] == 0)
                        --cnt;
            };

            if (type == 1) {
                if (l == r) {
                    int uv = lca(u, v);
                    pushbak(a[uv]);

                    for (; u != uv; u = anc[u])
                        pushbak(a[u]);

                    for (; v != uv; v = anc[v])
                        pushbak(a[v]);

                    res[i] = cnt;
                } else {
                    for (; dep[u]; u = anc[u])
                        if (lst[a[u]] < l)
                            pushbak(a[u]);

                    for (; dep[v]; v = anc[v])
                        if (lst[a[v]] < l)
                            pushbak(a[v]);

                    res[i] = cnt + sumk.getsum(l, l);
                }
            } else { //(type == 2)
                vector<int> A, B;

                for (int t = u; dep[t]; t = anc[t])
                    A.push_back(t);

                for (int t = v; dep[t]; t = anc[t])
                    B.push_back(t);

                A.push_back(pos[u]);
                reverse(A.begin(), A.end());
                B.push_back(pos[v]);
                reverse(B.begin(), B.end());

                // Part 1
                {
                    static int oth[MAXN];
                    int mid = 0;

                    if (l == r) {
                        while (mid + 1 < (int)A.size() && mid + 1 < (int)B.size() && A[mid + 1] == B[mid + 1])
                            ++mid;

                        for (int sw = 1; sw <= 2; ++sw, swap(A, B)) {
                            int cur = 0;

                            for (int j = (int)A.size() - 1; j >= 1; --j) {
                                int x = a[A[j]];

                                if (bak[x])
                                    cur += oth[x] - j;
                                else
                                    cur += (int)A.size() - j, pushbak(x);

                                oth[x] = j;

                                if (j <= mid)
                                    res[i] += cur;
                            }

                            roll(0);
                        }

                        res[i] -= mid;
                        pushbak(a[A[mid]]);

                        res[i] += ((ll)A.size() - (mid + 1)) * ((ll)B.size() - (mid + 1));
                    } else {
                        res[i] += sumk.getsum(l, l) * ((ll)A.size() - 1) * ((ll)B.size() - 1);
                    }

                    for (int j = mid + 1; j < (int)A.size(); ++j) {
                        int x = a[A[j]];

                        if (l != r && lst[x] >= l)
                            continue;

                        if (!bak[x]) {
                            pushbak(x);
                            oth[x] = j;
                            res[i] += ((ll)A.size() - j) * ((ll)B.size() - (mid + 1));
                        }
                    }

                    for (int j = mid + 1; j < (int)B.size(); ++j) {
                        int x = a[B[j]];

                        if (l != r && lst[x] >= l)
                            continue;

                        if (bak[x] >= 2)
                            continue;

                        if (bak[x] == 0) {
                            pushbak(x);
                            oth[x] = -1;
                            res[i] += ((ll)B.size() - j) * ((ll)A.size() - (mid + 1));
                        } else if (oth[x] != -1) {
                            pushbak(x);
                            res[i] += ((ll)B.size() - j) * (oth[x] - (mid + 1));
                        }
                    }

                    roll(0);
                }

                // Part 2
                {
                    ll bas = sumk.getsum(1, l);

                    for (int j = 1; j < (int)B.size(); ++j) {
                        int x = a[B[j]];

                        if (lst[x] < l && !bak[x]) {
                            pushbak(x);
                            bas += l - lst[x];
                        }

                        res[i] += bas;
                    }

                    roll(0);
                }
                {
                    ll bas = sumk.getsum(l, l) * r + sumb.getsum(l, l);
                    pushbak(a[A[0]]);

                    for (int j = 1; j < (int)A.size(); ++j) {
                        int x = a[A[j]];

                        if (!bak[x]) {
                            pushbak(x);
                            auto it = lower_bound(occ[x].begin(), occ[x].end(), l);
                            int lx = *prev(it);
                            int rx = min(*it, r + 1);
                            bas += rx - lx - 1;
                        }

                        res[i] += bas;
                    }

                    roll(0);
                }

                // Part3
                res[i] += sumk.getsum(1, l) * r + sumb.getsum(1, l);
            }

            roll(0);
        }

        sumk.add(RR + 1, nxt[RR] - 1, -1);
        sumb.add(RR + 1, nxt[RR] - 1, RR);
    }

    for (int i = 1; i <= m; ++i)
        printf("%lld\n", res[i]);
}

int main(void) {
    int T = read();

    while (T--)
        solve();

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 30
Accepted
time: 585ms
memory: 30268kb

input:

3
96399 70104 352607 503607 701698
198732
1 81463 87861
1 65504 83230
1 79936 87804
1 88830 88166
1 77973 44777
1 51799 44835
1 39775 61727
1 83170 89320
1 42936 24414
1 69822 72892
1 55122 88684
1 72042 54083
1 72498 89884
1 77599 46486
1 39184 62507
1 72082 59829
1 86411 83538
1 58199 47993
1 5312...

output:

45127
5737
5085
19923
18544
6711
19611
19417
16916
24479
22644
4887
14449
8162
20681
32179
18899
9711
18976
1580
42374
9017
17201
32000
6673
9735
33055
8807
15866
1438
27252
22947
5593
12337
25237
1885
1227
9374
40811
8363
8662
35623
14371
13956
12440
25347
3335
13005
31015
21176
15842
11330
9785
40...

result:

ok 590662 lines

Test #2:

score: 30
Accepted
time: 1148ms
memory: 31252kb

input:

3
93462 93462 198089 21092 490171
193889
2 66857 87119
2 66053 71005
1 38332 90069
2 88955 69730
2 44128 3255
2 43024 55262
2 56296 4917
2 64824 92036
1 35567 67670
2 55665 78399
2 47040 71743
2 44179 47165
2 19195 50559
1 39470 65813
2 47192 12119
2 87826 79538
2 35658 47364
1 46560 23526
2 91886 7...

output:

129514482565047
90552860056009
39770
140366242079658
2548889407192
36019588646234
5959587637653
138862401182438
27260
89122173277514
64418381921956
28322037491959
15304781080096
23011
9239208076161
159438659855932
22315524603837
20453
151786744147449
90755461139340
131500189927839
159232700655186
92...

result:

ok 578377 lines

Test #3:

score: 40
Accepted
time: 931ms
memory: 24608kb

input:

3
99069 21210 535118 478507 499996
192742
2 81987 60204
2 60168 56787
2 7020 58419
2 38493 50125
2 30099 66372
2 56061 16851
2 75140 25970
2 52005 43349
2 90823 30429
2 47148 40374
2 95394 30788
2 72437 70280
2 28664 97835
1 39731 70525
2 516 1729
2 76620 73423
2 61712 70480
2 31804 46927
2 30888 49...

output:

1919183134
9074765824
39903821891
27496108727
1199159402601
578554632061
18171350107
9365803115
464957486766
151286824704
508443655984
1023168094240
206600585106
12915
585684040
88622548437
522215022299
1084223397530
48460036608
5780
334295128974
447300213691
55864648016
1393901874904
7022
319553336...

result:

ok 584730 lines