Problem A. Perfectly Balanced
题意:给定一个字符串,每次询问一个子串,问是否是几乎平衡的。
几乎平衡的定义是,从子串中删除一个字符后,长度为偶数,且前半段中每个字符的出现次数与后半段相等。
A1 中字符集来自小写字符。A2 中字符集来自任意 int。
分析:再考虑弱化,如果字符集只有 {0, 1},那么我们只要先判断下长度是否为奇数,然后枚举一下删哪个位置,然后树状数组比较一下两段 1 的个数是否一样即可。
再考虑如何不枚举删哪个位置,哪么就讨论从哪边删,然后看两边的 diff 是否是一即可。设 S(l, r) 表示 [l, r) 这个区间里 1 出现的次数,那么就是比较一下
- S(ml, r) – S(l, ml) = 1 或者
- S(l, mr) – S(mr, r) = 1。
因此对于 A1,我们只要开 25 棵树状数组就能通过。对于字符集任意的情况,我们把所有数字映射成一个随机 uint,然后看 diff 是否恰好是某个字符的映射即可。代码反而比 A1 更简单。
#include <lastweapon/bitwise>
#include <lastweapon/fenwicktree>
#include <bits/stdc++.h>
using namespace lastweapon;
mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<uint64_t> rnd(0, ULLONG_MAX);
const int N = int(1e6) + 9;
map<int, uLL> H;
set<uLL> inHash;
uLL h(int x) {
    if (!CTN(H, x)) inHash.insert(H[x] = rnd(gen));
    return H[x];
}
fenwick_tree<uLL> T;
int a[N];
int n;
int f(int l, int r) {
    if ((r-l)&1) return 0;
    int m = (l+r)/2;
    uLL L = T.sum(l), R = T.sum(r+1), ML = T.sum(m), MR = T.sum(m+1);
    return CTN(inHash, (MR-L)-(R-MR)) || CTN(inHash, (R-ML)-(ML-L));
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    Rush {
        printf("Case #%d: ", ++Case);
        H.clear(); inHash.clear();
        RD(n); T = fenwick_tree<uLL>(n+1);
        REP_1(i, n) T.add(i, h(RD(a[i])));
        int z = 0; Rush {
            int cmd, l, r; RD(cmd, l, r);
            if (cmd == 1) {
                T.add(l, h(r) - h(a[l]));
                a[l] = r;
            } else {
                z += f(l, r);
            }
        }
        printf("%d\n", z);
    }
}
Problem B. Balance Sheet
我们把 day 看成点,client 看成边,那么显然是 dag dp。
对于对于 top K 只要用 multiset 记录 dp 值即可。
const int N = int(1e6) + 9;
typedef pair<pair<int, int>, int> rec;
multiset<LL> z;
map<int, multiset<LL> > c, d;
vector<rec> e;
int a[N],b[N],x[N],y[N];
int n, k;
void fix(multiset<LL>& x) {
    while (x.size() > k) x.erase(x.begin());
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("balance_sheet_input.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    Rush {
        printf("Case #%d: ", ++Case);
        z.clear(); RD(n, k);
        c.clear(); d.clear(); e.clear();
        REP_1(i, n) {
            RD(a[i],b[i],x[i],y[i]);
            e.PB({{a[i], x[i]}, -i});
            e.PB({{b[i], y[i]}, i});
        }
        SRT(e);
        for (auto& t: e) {
            if (t.se < 0) { // buy
                int id = -t.se;
                c[id].insert(0);
                for (auto i: d[a[id]]) {
                    c[id].insert(i + x[id]);
                    fix(c[id]);
                }
                for (auto i: c[id]) {
                    z.insert(i); fix(z);
                }
            } else { // sell
                int id = t.se;
                for (auto i : c[id]) {
                    d[b[id]].insert(i - y[id]);
                    fix(d[b[id]]);
                }
            }
        }
        Int zz = 0; for (auto& t: z) zz += Int(t);
        cout << zz <<endl;
    }
}
Problem C. Balance Scale
n 袋饼干,第 i 待里有 C_i 块重 W_i 的饼干。
从所有的饼干中任取 k 个,问其中最重的一块饼干(如果有多个,任取其一)来自第一袋的概率。
Problem D. Work-Life Balance
题意:给定长度为 n 的序列 {Ai},支持 m 次单点修改,问每次修改后至少多少次 swap 操作,可以让序列的一个给定的前缀和等于剩下部分的后缀和。
- D1 中 Ai ∈ {1,2,3},可以交换任意位置。
- D2 中 Ai ∈ {1,2},只可以交换相邻位置。
分析:D1 的情况显然可以贪心。




 Alca
 Alca Amber
 Amber Belleve Invis
 Belleve Invis Chensiting123
 Chensiting123 Edward_mj
 Edward_mj Fotile96
 Fotile96 Hlworld
 Hlworld Kuangbin
 Kuangbin Liyaos
 Liyaos Lwins
 Lwins LYPenny
 LYPenny Mato 完整版
 Mato 完整版 Mikeni2006
 Mikeni2006 Mzry
 Mzry Nagatsuki
 Nagatsuki Neko13
 Neko13 Oneplus
 Oneplus Rukata
 Rukata Seter
 Seter Sevenkplus
 Sevenkplus Sevenzero
 Sevenzero Shirleycrow
 Shirleycrow Vfleaking
 Vfleaking wangzhpp
 wangzhpp Watashi
 Watashi WJMZBMR
 WJMZBMR Wywcgs
 Wywcgs XadillaX
 XadillaX Yangzhe
 Yangzhe 三途川玉子
 三途川玉子 About.me
 About.me Vijos
 Vijos
