A - Broken Keyboard
按照题意模拟即可啦,只需要看连续这一段的字母个数的奇偶性即可。

#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
    printf("\n\nTime used:
    system("pause");
#endif
}
string s;
set<char> ans;

inline void solve()
{
    ans.clear();
    cin >> s;

    s.push_back('#');int n = s.size();
    int cnt = 1;
    for (int i = 0; i < n - 1; ++i)
    {
        if (s[i + 1] != s[i])
        {
            if (cnt & 1)
                ans.insert(s[i]);
            cnt = 1;
        }
        else
            cnt++;
    }
    for(auto i : ans)
        cout << i;
    cout << '\n';
}

int main()
{
    TIME__START = clock();
    int Test = 1;
    scanf(
    while (Test--)
    {
        solve();
        // if (Test)
        //     putchar('\n');
    }
    TIME__END = clock();
    program_end();
    return 0;
}

B - Binary Palindromes
把串分成三类:0 的个数和 1 的个数都是奇数、其中一个是奇数另一个是偶数、两个都是偶数,只有第一类串不能构成回文,我们就需要尽量消除第一类的。
有几种办法可以消除:优先考虑两个第一类串互相交换一个 0 和 1,这样就变成第三类串,这样最后只剩下 0 个或 1 个一类串,这个时候用一个第二类串去和剩下的一类串交换一次即可。这样,所有的一类串就消除完了。
...不过我代码中分类编号有点不一样就是了

#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
    printf("\n\nTime used:
    system("pause");
#endif
}
int t1, t2, t3, ans;

inline void solve()
{
    ans = 0;
    int n;
    cin >> n;
    t1 = t2 = t3 = 0;
    for (int i = 1; i <= n; ++i)
    {
        string s;
        cin >> s;
        int _0 = 0, _1 = 0;
        for (auto j : s)
            (j == '0') ? _0++ : _1++;
        if ((_0 & 1) && (_1 & 1))
            t3++;
        else if ((!(_0 & 1)) && (!(_1 & 1)))
            t1++;
        else
            t2++;
    }
    ans = t1 + t2 + (t3 / 2) * 2;
    if (t2 && (t3 & 1))
        ans++;
    cout << ans << '\n';
}

int main()
{
    TIME__START = clock();
    int Test = 1;
    scanf(
    while (Test--)
    {
        solve();
        // if (Test)
        //     putchar('\n');
    }
    TIME__END = clock();
    program_end();
    return 0;
}

C - Minimize The Integer
贪心,从高位往地位,当前这一位是奇数的话就找一个满足位置最靠前的数字最小的偶数,并且该偶数小于该奇数的话就把那个偶数移过来;当前位置是偶数的话同理。之后用一个 vis 记录一下哪些位置被移动过即可。

#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
    printf("\n\nTime used:
    system("pause");
#endif
}
int n;
char s[N];
vector<int> pos[10];
int ans[N];
bool vis[N];

inline void solve()
{
    scanf(
    n = strlen(s + 1);
    mem(vis, 0, n, bool);
    for (int i = 0; i < 10; ++i)
        pos[i].resize(0);
    for (int i = 1; i <= n; ++i)
        pos[s[i] - '0'].push_back(i);
    for (int i = 0; i < 10; ++i)
        reverse(vecall(pos[i]));
    int e = 0;
    for (int i = 1; i <= n; ++i)
    {
        if (vis[i])
            continue;
        if ((s[i] - '0') & 1)
        {
            int mnpos = inf, num = -1;
            for (int j = 0; j < 10; j += 2)
            {
                if (!pos[j].empty() && mnpos > pos[j].back())
                    mnpos = pos[j].back(), num = j;
            }
            if (num != -1 && num < s[i] - '0')
            {
                ans[++e] = num;
                i--;
                vis[pos[num].back()] = 1;
            }
            else
                ans[++e] = s[i] - '0';
            pos[ans[e]].pop_back();
        }
        else
        {
            int mnpos = inf, num = -1;
            for (int j = 1; j < 10; j += 2)
            {
                if (!pos[j].empty() && mnpos > pos[j].back())
                    mnpos = pos[j].back(), num = j;
            }
            if (num != -1 && num < s[i] - '0')
                ans[++e] = num, vis[pos[num].back()] = 1, i--;
            else
                ans[++e] = s[i] - '0';
            pos[ans[e]].pop_back();
        }
        printf(
    }
    cout << '\n';
}

int main()
{
    TIME__START = clock();
    int Test = 1;
    scanf(
    while (Test--)
    {
        solve();
        // if (Test)
        //     putchar('\n');
    }
    TIME__END = clock();
    program_end();
    return 0;
}

D - Salary Changing
二分,下界显然就是所有的 $l_i$ 的中位数,接下来二分一个答案 $x$,check 的时候贪心:显然每个数能选得越小就越好,这样花的钱总和就越小。按照 $l_i$ 排序,把 $l_i$ 大的那些尽量选做中位数之后的,这样剩下的就全部选 $l_i$,这样就可以保证选出来的总和最小。

#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
    printf("\n\nTime used:
    system("pause");
#endif
}
int n;
ll s, suml;
struct person
{
    ll l, r;
    bool operator<(const person &rhs) const
    {
        return l > rhs.l || (l == rhs.l && r > rhs.r);
    }
} p[N];

bool f1(ll x)
{
    int numr = 0;
    ll sum = suml, ss = s;
    for (int i = 1; i <= n; ++i)
    {
        if (p[i].r >= x)
            numr++, sum -= p[i].l, ss -= max(p[i].l, x);
        if (ss < 0)
            return false;
        if (numr == (n + 1) / 2)
        {
            break;
        }
    }
    if (numr < (n + 1) / 2 || ss < sum)
        return false;
    else
        return true;
}

inline void solve()
{
    suml = 0;
    scanf(
    for (int i = 1; i <= n; ++i)
        scanf(
    sort(p + 1, p + n + 1);
    ll L = p[n / 2 + 1].l, R = s, ans = 0;
    while (L <= R)
    {
        ll mid = (L + R) >> 1;
        bool chk = f1(mid);
        if (chk)
            ans = mid, L = mid + 1;
        else
            R = mid - 1;
    }
    cout << ans << '\n';
}

int main()
{
    TIME__START = clock();
    int Test = 1;
    scanf(
    while (Test--)
    {
        solve();
        // if (Test)
        //     putchar('\n');
    }
    TIME__END = clock();
    program_end();
    return 0;
}

E1 - Voting (Easy Version)
E2 - Voting (Hard Version)

这里只说 E2。
按照 $m_i$ 排序,从 $m_i$ 大的一边入手。显然对于一个人,买了的人数+$m_i$ 比他小的人数 < 自己的 $m_i$ 的话就需要从 $m_i$ 大的人里面买,贪心地买的越少越好,这里一个 set 或者优先队列就可以。

#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
    printf("\n\nTime used:
    system("pause");
#endif
}
int n;
struct voter
{
    int p, m;
    bool operator<(const voter &rhs) const { return m < rhs.m; }
} a[N];
multiset<int> s;
ll ans;

inline void solve()
{
    s.clear();
    scanf(
    for (int i = 1; i <= n; ++i)
        scanf(
    sort(a + 1, a + n + 1);
    int buyer = 0;
    ans = 0;
    for (int i = n; i >= 1; --i)
    {
        s.insert(a[i].p);
        if (a[i].m > i - 1 + buyer)
        {
            while (i - 1 + buyer != a[i].m)
            {
                ans += (*s.begin());
                s.erase(s.begin());
                buyer++;
            }
        }
    }
    cout << ans << '\n';
}

int main()
{
    TIME__START = clock();
    int Test = 1;
    scanf(
    while (Test--)
    {
        solve();
        // if (Test)
        //     putchar('\n');
    }
    TIME__END = clock();
    program_end();
    return 0;
}

F - Red-White Fence
显然对于每一个 $b_i$ 都是一个单独的问题。接下来开始入手。
把 $a_i$ 从小到大排序并且 unique,设 $cnt(i)$ 表示高度为 $i$ 的白条个数,设 $dp(i,j)$ 表示前 $i$ 小里面选了 $j$ 个白条的方案数,有下面的转移方程:$dp(i,j)=dp(i-1,j)+2\times dp(i-1,j-1)+dp(i-1,j-2)\times [cnt(i)\ge 2]$,分别表示不选、只选一个、选两个。
但这个 dp 是 $\mathcal{O}(n^2)$ 的,怎么优化?
优化就考虑把上面最后一项分成两部分:第一部分,$cnt(i)=1$,那么就有 $dp(i,j)=dp(i-1,j)+2\times dp(i-1,j-1)$,这是一个牛顿二项式那种,可以根据组合意义,得到 $dp(i,j)=\binom{cntn}{i}2^i$;第二部分,$cnt(i)\ge 2$,那么就有 $dp(i,j)=\binom{2\cdot cntm}{i}$。上面 $cntn$ 表示 $cnt(i)=1$ 的白条个数,$cntm$ 表示 $cnt(i)\ge 2$ 的白条个数,这两个东西可以写成俩生成函数:$F=\sum\limits_{k=0}^{cntn}\binom{cntn}{k}2^kx^k$ 和 $G=\sum\limits_{k=0}^{2\cdot cntm}\binom{2\cdot cntm}{k}x^k$,用 NTT 把这两个卷起来,然后 $F(i)$ 的系数就是 $i+1+b$ 的贡献。
时间复杂度 $\mathcal{O}(nk\log n)$。

#include <bits/stdc++.h>
#define ll long long
#define ls id << 1
#define rs id << 1 | 1
#define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
#define memarray(array, value) memset(array, value, sizeof(array))
#define fillarray(array, value, begin, end) fill((array) + (begin), (array) + (end) + 1, value)
#define fillvector(v, value) fill((v).begin(), (v).end(), value)
#define pb(x) push_back(x)
#define st(x) (1LL << (x))
#define pii pair<int, int>
#define mp(a, b) make_pair((a), (b))
#define Flush fflush(stdout)
#define vecfirst (*vec.begin())
#define veclast (*vec.rbegin())
#define vecall(v) (v).begin(), (v).end()
#define vecupsort(v) (sort((v).begin(), (v).end()))
#define vecdownsort(v, type) (sort(vecall(v), greater<type>()))
#define veccmpsort(v, cmp) (sort(vecall(v), cmp))
using namespace std;
const int N = 500050;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0);
clock_t TIME__START, TIME__END;
void program_end()
{
#ifdef ONLINE
    printf("\n\nTime used:
    system("pause");
#endif
}
const int Lim = 1 << 20;
struct polyntt
{
    typedef vector<int> Vi;
    int add(int a, int b) { return (a += b) >= mod ? a - mod : a; }
    int sub(int a, int b) { return (a -= b) >= 0 ? a : a + mod; }
    int mul(long long a, int b) { return a * b
    int ksm(int a, int b)
    {
        int ret = 1;
        while (b)
        {
            if (b & 1)
                ret = 1ll * ret * a
            a = 1ll * a * a
            b >>= 1;
        }
        return ret;
    }

    int rev[Lim + 5], lg2[Lim + 5], rt[Lim + 5], irt[Lim + 5];
    int n, k, lim, type;

    void init() //求原根
    {
        for (int i = 2; i <= Lim; i++)
            lg2[i] = lg2[i >> 1] + 1;
        rt[0] = 1;
        rt[1] = ksm(3, (mod - 1) / Lim); //第一个原根
        irt[0] = 1;
        irt[1] = ksm(rt[1], mod - 2); //费马小
        for (int i = 2; i <= Lim; i++)
        {
            rt[i] = mul(rt[i - 1], rt[1]);
            irt[i] = mul(irt[i - 1], irt[1]);
        }
    }

    void NTT(Vi &f, int type, int lim)
    {
        f.resize(lim);
        int w, y, l = lg2[lim] - 1;
        for (int i = 1; i < lim; i++)
        {
            rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << l);
            if (i >= rev[i])
                continue;
            swap(f[i], f[rev[i]]); //蝴蝶
        }
        l = Lim >> 1;
        for (int mid = 1; mid < lim; mid <<= 1)
        {
            for (int j = 0; j < lim; j += (mid << 1))
            {
                for (int k = 0; k < mid; k++)
                {
                    w = type == 1 ? rt[l * k] : irt[l * k];
                    y = mul(w, f[j | k | mid]);
                    f[j | k | mid] = sub(f[j | k], y);
                    f[j | k] = add(f[j | k], y);
                }
            }
            l >>= 1;
        }
        if (type == 1)
            return;
        y = ksm(lim, mod - 2);
        for (int i = 0; i < lim; i++)
            f[i] = mul(f[i], y);
    }

    void NTTTMD(Vi &F, Vi &G)
    {
        int n = F.size() + G.size();
        lim = 1;
        while (lim <= n)
            lim <<= 1;
        F.resize(lim);
        G.resize(lim);
        NTT(F, 1, lim), NTT(G, 1, lim);
        for (int i = 0; i < lim; i++)
            F[i] = mul(F[i], G[i]);
        NTT(F, -1, lim);
        F.resize(n - 1);
    }
} myntt;
int n, k, a[N], b[10], q[N], Q, cnt[N];
ll ans[1000050], fac[N], invfac[N];
ll C(ll n, ll m) { return n < m ? 0 : (fac[n] * invfac[m]

inline void solve()
{
    myntt.init();
    fac[0] = invfac[0] = 1;
    for (int i = 1; i <= 3e5; ++i)
        fac[i] = fac[i - 1] * i
    scanf(
    for (int i = 1; i <= n; ++i)
        scanf(
    for (int i = 1; i <= k; ++i)
        scanf(
    scanf(
    for (int i = 1; i <= Q; ++i)
        scanf(
    sort(a + 1, a + n + 1);
    int m = unique(a + 1, a + n + 1) - a - 1;
    for (int T = 1; T <= k; ++T)
    {
        vector<int> F, G;
        int cntn = 0, cntm = 0;
        for (int i = 1; i <= m && a[i] < b[T]; ++i)
        {
            if (cnt[a[i]] == 1)
                cntn++;
            else
                cntm++;
        }
        for (int i = 0; i <= cntn; ++i)
            F.push_back(myntt.mul(C(cntn, i), myntt.ksm(2, i)));
        for (int i = 0; i <= 2 * cntm; ++i)
            G.push_back(C(2 * cntm, i));
        myntt.NTTTMD(F, G);
        for (int i = 0; i < (int)F.size(); ++i)
            ans[i + 1 + b[T]] = myntt.add(ans[i + 1 + b[T]], F[i]);
    }
    for (int i = 1; i <= Q; ++i)
        printf(
}

int main()
{
    TIME__START = clock();
    int Test = 1;
    // scanf(
    while (Test--)
    {
        solve();
        // if (Test)
        //     putchar('\n');
    }
    TIME__END = clock();
    program_end();
    return 0;
}