7/12 训练笔记

闲话

打 OI Bingo 然后大力卡时卡空间,贺了最优解之后成功 Bingo.
rep (i, 0, (int)v.size() - 1) v.push_back(1);在 vector v 本来就有内容的情况下会持续循环。
rep (i, 1, n) rep (i, 1, n) cin >> a[i];似乎会出问题。

P4137 Rmq Problem / mex

回滚莫队题,莫队笔记
考虑 mex 在删除时是好维护的:维护一个 cnt 数组,删空了就和 mex 比一下哪个小,然后更新。
但是添加不好做,所以使用回滚莫队。
代码:

#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l; i <= r; i++)
using namespace std;
int B;
int a[200010], b[200010], bel[200010], cnt[200010], cnt1[200010], ans[200010], st[1010], res[1010], n, m, mex;
int id(int x) {
    return bel[x];
}
struct query {
    int l, r, id1;
    query(int l = 0, int r = 0, int id1 = 0):l(l), r(r), id1(id1) {}
    bool operator<(query o) {
        return (id(l) != id(o.l)) ? id(l) < id(o.l) : r > o.r;
    }
    query operator=(query o) {
        l = o.l;
        r = o.r;
        id1 = o.id1;
        return *this;
    }
}q[200010];
void del(int x) {
    cnt[x]--;
    if (!cnt[x]) mex = min(mex, x);
}
int bruteForce(int l, int r) {
    int mex = 0;
    int mmin = 0x3f3f3f3f, mmax = 0;
    rep (i, l, r) {
        mmin = min(mmin, a[i]);
        mmax = max(mmax, a[i]);
    }
    rep (i, 0, mmax + 1) {
        cnt1[i] = 0;
    }
    rep (i, l, r) {
        cnt1[a[i]]++;
    }
    rep (i, 0, mmax + 1) {
        if (cnt1[i] == 0) {
            mex = i;
            break;
        }
    }
    return mex;
}
int main() {
    cin >> n >> m;
    B = sqrt(n);
    rep (i, 1, n) {
        cin >> a[i];
        bel[i] = (i - 1) / B + 1;
        if (!st[bel[i]]) st[bel[i]] = i;
        // cout << bel[i] << " ";
        cnt[a[i]]++;
    }
    // cout << "\n";
    rep (i, 1, m) {
        cin >> q[i].l >> q[i].r;
        q[i].id1 = i;
    }
    sort(q + 1, q + m + 1);
    // rep (i, 1, m) {
    //     cout << q[i].l << " " << q[i].r << "\n";
    // }
    mex = bruteForce(1, n);
    rep (i, 1, (n - 1) / B + 1) {
        res[i] = bruteForce(st[i], n);
        // cout << st[i] << " " << n << " " << bruteForce(st[i], n) << "\n";
    }
    // rep (i, 46, 83) {
    //     cout << a[i] << " ";
    // }
    // cout << "\n";
    // rep (i, 64, 97) {
    //     cout << a[i] << " ";
    // }
    // cout << "\n";
    int l = 1, r = n;
    rep (i, 1, m) {
        if (id(l) != id(q[i].l)) {
            l = st[id(q[i].l)];
            mex = res[id(l)];
            r = n;
            rep (i, 1, n) {
                cnt[a[i]] = 0;
            }
            rep (i, l, n) {
                cnt[a[i]]++;
            }
        }
        // cout << i << " " << l << " " << mex << "\n";
        if (id(q[i].r) != id(l)) {
            // if (q[i].l == 66) {
            //     cout << l << "\n";
            //     rep (i, 1, 10) {
            //         cout << cnt[i] << " ";
            //     }
            //     cout << "\n";
            //     cout << mex << "\n";
            // }
            while (r > q[i].r) del(a[r--]);
            int t = mex;
            // if (q[i].l == 51) cout << t << " " << l << " " << r << "\n";
            // if (q[i].l == 46 && q[i].r == 80) {
            //     cout << mex << " " << l << " " << r << "\n";
            //     rep (i, 0, 9) {
            //         cout << cnt[i] << " ";
            //     }
            // }
            int tl = l;
            while (l < q[i].l) del(a[l++]);
            ans[q[i].id1] = mex;
            if (q[i].l == 65) {
                // cout << "Here1\n";
                // cout << i << " " << mex << "\n";
            }
            // if (q[i].l == 66) {
            //     cout << "Here\n";
            //     cout << i << " " << mex << "\n";
            // }
            mex = t;
            l = tl;
            // rep (i, 1, n) {
            //     cnt[a[i]] = 0;
            // }
            rep (j, tl, q[i].l - 1) {
                cnt[a[j]]++;
            }
            // if (q[i].l == 51 && q[i].r == 83) {
            //     cout << "here\n";
            //     cout << tl << " " << q[i].l << "\n";
            //     rep (j, tl, q[i].l - 1) {
            //         cout << i << " " << a[i] << "\n";
            //     }
            // }
            // if (q[i].l == 51) {
            //     cout << l << " " << r << "\n";
            //     rep (i, 0, 9) {
            //         cout << cnt[i] << " ";
            //     }
            //     cout << "\n";
            // }
        } else {
            ans[q[i].id1] = bruteForce(q[i].l, q[i].r);
        }
    }
    rep (i, 1, m) {
        cout << ans[i] << "\n";
    }
}

P2558 [AHOI2002] 网络传输

进行一个规律的找。
发现序列实际上是这样构成的(省略了底数 \(k\),只写了指数):\(0, 1, 01, 2, 02, 12, 012, \dots\)
那么可以发现每次就是加一个数然后把之前的东西连到这个数前面。
那么模拟就好了,__int128可过。

#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l; i <= r; i++)
using namespace std;
void write(__int128 a) {
    if (a <= 9) {
        putchar(a + '0');
    } else {
        write(a / 10);
        putchar(a % 10 + '0');
    }
}
__int128 qpow(int x, int y) {
    __int128 a = 1;
    rep (i, 1, y) {
        a *= x;
    }
    return a;
}
int k, p;
__int128 ans;
vector<vector<int> > v;
void calc() {
    for (auto i:v.back()) {
        ans += qpow(k, i);
    }
    write(ans);
}
int main() {
    cin >> k >> p;
    p--;
    if (p == 0) {
        cout << 1 << "\n";
    } else {
        v.push_back({0});
        int cnt = 1;
        while (p) {
            v.push_back({cnt});
            p--;
            if (!p) {
                calc();
                return 0;
            }
            vector<int> v1;
            // cout << "[" << p << " " << v.size() << "]\n";
            int sz = v.size() - 2;
            rep (i, 0, sz) {
                v1.clear();
                v1 = v[i];
                v1.push_back(cnt);
                v.push_back(v1);
                p--;
                if (!p) {
                    calc();
                    return 0;
                }
            }
            // cout << p << " ";
            // for (auto i:v.back()) {
            //     cout << i << " ";
            // }
            // cout << "\n";
            cnt++;
        }
    }
}

P2673 《瞿葩的数字游戏》T1-数字王国的门神

结论为:答案是 \(\frac{10}{89}\) 的第 \(M\) 至第 \(N\) 位小数。
生成函数应该能把这个推出来吧。

#include <stdio.h>
int m, n, a = 1, b = 89;
int main() {
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= n + 1; i++) {
        a %= b;a *= 10;
        if (i >= m + 1) {
            printf("%d", a / b);
        }
    }
}
posted @ 2024-07-12 20:05  IANYEYZ  阅读(10)  评论(1编辑  收藏  举报