CodeForces Gym 101620简要题解

来源:互联网 发布:短信群发平台软件 编辑:程序博客网 时间:2024/06/05 14:35

Assignment Algorithm

模拟。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 55;char a[MAXN][MAXN];int n, m;inline void Solve(char c){    vector <pii> row;    int cnt_1 = 0, cnt_2 = 0, t = 1, l = 0, r = 0;    for (int j = 0; j < 11; j ++)        cnt_1 += a[1][j] == '-', cnt_2 += a[n / 2 + 2][j] == '-';    if (cnt_1 || cnt_2)    {        if (cnt_1)            row.pb(mp(cnt_1, 1));        if (cnt_2)            row.pb(mp(cnt_2, n / 2 + 2));    }    else    {        for (int i = 0; i < n + 3; i ++)        {            int cnt = 0;            for (int j = 0; j < 11; j ++)                cnt += a[i][j] == '-';            if (cnt)                row.pb(mp(cnt, i));        }    }    sort(row.begin(), row.end(), greater <pii> ());    for (int i = 1; i < row.size(); i ++)        if (row[i].xx == row[0].xx)            t = i + 1;    for (int i = 0; i < t; i ++)        row[i].xx = min(min(row[i].yy, n + 2 - row[i].yy), abs(row[i].yy - (n / 2 + 1)));    sort(row.begin(), row.begin() + t);    for (int i = 0; i < n + 3; i ++)    {        for (int j = 0; j < 5; j ++)            l += a[i][j] == '-';        for (int j = 6; j < 11; j ++)            r += a[i][j] == '-';    }    int idx = row[0].yy;    if (a[idx][4] == '-' || a[idx][6] == '-')    {        if (a[idx][4] != '-')            a[idx][6] = c;        else if (a[idx][6] != '-')            a[idx][4] = c;        else if (l >= r)            a[idx][4] = c;        else            a[idx][6] = c;    }    else if (a[idx][2] == '-' || a[idx][8] == '-')    {        if (a[idx][2] != '-')            a[idx][8] = c;        else if (a[idx][8] != '-')            a[idx][2] = c;        else if (l >= r)            a[idx][2] = c;        else            a[idx][8] = c;    }    else if (a[idx][0] == '-' || a[idx][10] == '-')    {        if (a[idx][0] != '-')            a[idx][10] = c;        else if (a[idx][10] != '-')            a[idx][0] = c;        else if (l >= r)            a[idx][0] = c;        else            a[idx][10] = c;    }    else if (a[idx][5] == '-')    {        a[idx][5] = c;    }    else    {        if (a[idx][1] != '-')            a[idx][9] = c;        else if (a[idx][9] != '-')            a[idx][1] = c;        else if (l >= r)            a[idx][1] = c;        else            a[idx][9] = c;    }}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read();    for (int i = 0; i < n + 3; i ++)        scanf("%s", a[i]);    for (int i = 0; i < m; i ++)        Solve(i + 'a');    for (int i = 0; i < n + 3; i ++, putchar(10))        for (int j = 0; j < 11; j ++)            putchar(a[i][j]);    return 0;}

Buffalo Barricades

从上到下扫描线,用set维护当前的情况,并记录每个点的父亲,最后并查集扫一遍维护。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 300005;struct Event{    int typ, x, y, i;    bool operator < (const Event &b) const    {        return y > b.y || (y == b.y && typ > b.typ);    }} a[MAXN << 1];int n, m, f[MAXN], tmp[MAXN], tag[MAXN], ans[MAXN], par[MAXN];set <pii> s;inline int Find(int x){    while (x ^ f[x])        x = f[x] = f[f[x]];    return x;}inline void Merge(int x, int y){    if (x ^ y)        f[x] = y, tag[y] += tag[x];}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)        a[i].x = Read(), a[i].y = Read(), a[i].i = i, a[i].typ = 1;    m = Read();    for (int i = n + 1; i <= n + m; i ++)        a[i].x = Read(), a[i].y = Read(), a[i].i = i - n, a[i].typ = 2;    sort(a + 1, a + n + m + 1);    for (int i = 1; i <= n + m; i ++)        if (a[i].typ == 1)        {            auto it = s.lower_bound(mp(a[i].x, -1));            if (it != s.end())                tmp[it -> yy] ++;        }        else        {            auto it = s.insert(mp(a[i].x, a[i].i)).xx, jt = it;            if (jt != -- s.end())                par[a[i].i] = (++ jt) -> yy;            while (it != s.begin())            {                jt = it, jt --;                if (jt -> yy > a[i].i)                    s.erase(jt);                else                    break;            }        }    for (int i = 1; i <= m; i ++)        f[i] = i;    for (int i = m; i; i --)        ans[i] = tag[Find(i)] += tmp[i], Merge(Find(i), Find(par[i]));    for (int i = 1; i <= m; i ++)        printf("%d\n", ans[i]);    return 0;}

Cumulative Code

fk(x)表示k层的子树的prufer序列和,f(x)=ax+bx2+c,然后就可以递推了。

询问的时候记忆化搜索,将k层及以下的情况记下来,注意一些边界情况。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 32780;struct Node{    LL a, b, c;    Node(LL a = 0, LL b = 0, LL c = 0):a(a), b(b), c(c) {}    Node operator + (const Node &d) const { return Node(a + 2 * d.a + d.b, b, c + d.c); };    Node operator - (const Node &d) const { return Node(a + 2 * d.a + d.b, b, c + d.c + d.a); }} f[16][MAXN];int tim, vis[16][MAXN];inline Node Solve(int n, int a, int d, int m, bool p){    if (n == 1)        return Node(0, 1, 0);    bool mem = n <= 15 && a + d * m >= (1 << n) - 1 && p;    if (mem && vis[n][a] == tim)        return f[n][a];    Node ret(0, 0, 0);    int cur = a;    if (cur < (1 << n - 1) - 1 && m)    {        int t = min(m, ((1 << n - 1) - 1 - cur - 1) / d + 1);        ret = ret + Solve(n - 1, cur, d, t, true), cur += t * d, m -= t;    }    cur -= (1 << n - 1) - 1;    if (!p)    {        if (!cur && m)            m --, cur += d, ret.a += 2, ret.c ++;        cur --;    }    if (cur < (1 << n - 1) - 1 && m)    {        int t = min(m, ((1 << n - 1) - 1 - cur - 1) / d + 1);        ret = ret - Solve(n - 1, cur, d, t, p), cur += t * d, m -= t;    }    cur -= (1 << n - 1) - 1;    if (p && m)        ret.b ++;    if (mem)        vis[n][a] = tim, f[n][a] = ret;    return ret;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    int n = Read(), q = Read();    while (q --)    {        int a = Read() - 1, d = Read(), m = Read();        tim ++;        Node ret = Solve(n, a, d, m, false);        printf("%lld\n", ret.a + ret.c);    }    return 0;}

Donut Drone

(x,0)c次的情况记下来,询问可以暴力。

考虑修改,倒着推回去,不难发现最后一定是一段区间被影响了,也可以暴力维护。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 2005;int n, m, q, tim, cur_x, cur_y, vis[MAXN], lst[MAXN], nxt[MAXN], a[MAXN][MAXN];inline int R(int x) { x %= n; return x < 0 ? x + n : x; }inline int C(int x) { x %= m; return x < 0 ? x + m : x; }inline int FindNext(int x, int y){    int val = -1, ret = -1;    for (int i = x - 1; i <= x + 1; i ++)        if (val < a[R(i)][C(y + 1)])            ret = i, val = a[R(i)][C(y + 1)];    return ret;}inline int Jump(int x, int y){    for (; y < m; x = R(FindNext(x, y ++)));    return x;}inline int Move(int t){    if (t >= m - cur_y)        while (cur_y)            cur_x = R(FindNext(cur_x, cur_y)), cur_y = C(cur_y + 1), t --;    tim ++;    while (t >= m)    {        t -= m, cur_x = nxt[cur_x];        if (vis[cur_x] == tim)            t %= lst[cur_x] - t;        vis[cur_x] = tim, lst[cur_x] = t;    }    while (t)        cur_x = R(FindNext(cur_x, cur_y)), cur_y = C(cur_y + 1), t --;}inline void Modify(int x, int y){    int pos = Jump(x, y);    pii cur = mp(x, x);    while (y)    {        y --;        pii nxt = mp(INT_MAX, INT_MIN);        for (int i = cur.xx + 1; i >= cur.xx - 1; i --)        {            int p = FindNext(i, y);            if (p >= cur.xx && p <= cur.yy)                nxt.xx = i;        }        for (int i = cur.yy - 1; i <= cur.yy + 1; i ++)        {            int p = FindNext(i, y);            if (p >= cur.xx && p <= cur.yy)                nxt.yy = i;        }        if (nxt.xx > nxt.yy)            return ;        cur = nxt;    }    if (cur.yy - cur.xx >= n)        for (int i = 0; i < n; i ++)            nxt[i] = pos;    else        for (int i = cur.xx; i <= cur.yy; i ++)            nxt[R(i)] = pos;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read();    for (int i = 0; i < n; i ++)        for (int j = 0; j < m; j ++)            a[i][j] = Read();    for (int i = 0; i < n; i ++)        nxt[i] = Jump(i, 0);    q = Read();    while (q --)    {        char opt[10];        scanf("%s", opt);        if (opt[0] == 'm')            Move(Read()), printf("%d %d\n", cur_x + 1, cur_y + 1);        else        {            int x = Read() - 1, y = Read() - 1;            a[x][y] = Read();            for (int i = x - 1; i <= x + 1; i ++)                Modify(R(i), C(y - 1));        }    }    return 0;}

Embedding Enumeration

首先必须是一棵二叉树,不然无解。

暴力做法可以f(i,j)表示当前还剩i的子树没有放,并且已经放的长的一行减去短的一行长度为j

事实上j大多数时候是1,而不是1的时候也可以比较方便地特判掉。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 300005;const int mod = 1e9 + 7;int n, ans, deg[MAXN], par[MAXN], nxt[MAXN], dis[MAXN], adj[MAXN][3], f[MAXN][4][4];vector <int> seq;inline void Addedge(int x, int y){    if (deg[x] == 3 || deg[y] == 3)        puts("0"), exit(0);    adj[x][deg[x] ++] = y, adj[y][deg[y] ++] = x;}inline void DFS(int x){    seq.pb(x);    for (int i = 0; i < deg[x]; i ++)        if (adj[x][i] ^ par[x])            par[adj[x][i]] = x, DFS(adj[x][i]);}inline bool Find(int x, int y, int z, int &r){    bool flg = false;    r = -1;    for (int i = 0; i < deg[x]; i ++)        if ((adj[x][i] ^ y) && (adj[x][i] ^ z))        {            if (flg)                return false;            flg = true, r = adj[x][i];        }    return true;}inline bool Chain(int x){    return deg[nxt[x]] == 1;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), Addedge(0, 1);    for (int i = 1; i < n; i ++)        Addedge(Read(), Read());    par[0] = -1, DFS(0);    for (int i = n; i; i --)    {        int x = seq[i], y;        if (deg[x] == 2)            Find(x, par[x], -1, y), nxt[x] = nxt[y], dis[x] = dis[y] + 1;        else            nxt[x] = x, dis[x] = 0;    }    f[0][1][0] = 1;    for (auto x : seq)        for (int i = 0; i <= deg[x]; i ++)            for (int j = 0, y = i == deg[x] ? n + 1 : adj[x][i], z, u, v; j <= deg[y]; j ++)                if (f[x][i][j])                    if (Find(x, par[x], y, u) && Find(y, x, z = j == deg[y] ? n + 1 : adj[y][j], v))                    {                        if (~u && ~v)                        {                            while (deg[u] == 2 && deg[v] == 2)                                Find(u, par[u], -1, u), Find(v, par[v], -1, v);                            if (!Find(u, par[u], -1, u) || !Find(v, par[v], -1, v))                                continue;                        }                        if (!~u && !~v)                            ans = (ans + f[x][i][j]) % mod;                        else                        {                            if (~v)                                swap(u, v);                            f[u][deg[u]][0] = (f[u][deg[u]][0] + f[x][i][j]) % mod;                            for (int k = 0; k < deg[u]; k ++)                                if (adj[u][k] ^ par[u])                                    f[u][k][deg[adj[u][k]]] = (f[u][k][deg[adj[u][k]]] + f[x][i][j]) % mod;                            if (Chain(u))                            {                                if (dis[u] >= 3 && (dis[u] & 1))                                    ans = (ans + f[x][i][j]) % mod;                            }                            else                                for (int t = 0, p = nxt[u], q, r; t < 2; t ++, p = par[p])                                    for (int k = 0; k < deg[p]; k ++)                                        if ((q = adj[p][k]) ^ par[p])                                            for (int l = 0; l < deg[q]; l ++)                                                if ((r = adj[q][l]) ^ p)                                                    if (Chain(r) && dis[r] + 1 == dis[u] - t)                                                        f[p][k][l] = (f[p][k][l] + f[x][i][j]) % mod;                        }                    }    return printf("%d\n", ans), 0;}

Faulty Factorial

分类讨论。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline LL Read(){    LL x = 0; int f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}LL n;int p, r;inline int Qow(int x, int y){    int r = 1;    for (; y; y >>= 1, x = 1LL * x * x % p)        if (y & 1)            r = 1LL * r * x % p;    return r;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), p = Read(), r = Read();    if (!r)    {        if (n <= 2 || n < p)            return puts("-1 -1"), 0;        return printf("%d 1\n", 2 + (p == 2)), 0;    }    if (n >= p * 2)        return puts("-1 -1"), 0;    int fac = 1;    for (int i = 1; i <= n; i ++)        if (i ^ p)            fac = 1LL * fac * i % p;    int inv = Qow(fac, p - 2);    if (n >= p)        return printf("%d %d\n", p, 1LL * inv * r % p), 0;    for (int i = 2; i <= n; i ++)    {        int v = 1LL * inv * i % p * r % p;        if (v < i)            return printf("%d %d\n", i, v), 0;    }    return puts("-1 -1"), 0;}

Gambling Guide

f(x)表示x走到n的期望步数,那么显然f(y)<f(x)才会移动。

类似Dijkstra维护转移。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 300005;priority_queue <pair <double, int>> q;double f[MAXN], sum[MAXN];vector <int> adj[MAXN];int n, m, cnt[MAXN];bool vis[MAXN];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read();    for (int i = 1, x, y; i <= m; i ++)        x = Read(), y = Read(), adj[x].pb(y), adj[y].pb(x);    f[n] = 0, q.push(mp(0, n));    for (int i = 1; i <= n; i ++)        sum[i] = adj[i].size();    while (!q.empty())    {        int x = q.top().yy;        q.pop();        if (vis[x])            continue;        vis[x] = true;        for (auto y : adj[x])            if (!vis[y])                cnt[y] ++, sum[y] += f[x], f[y] = sum[y] / cnt[y], q.push(mp(-f[y], y));    }    return printf("%lf\n", f[1]), 0;}

Hidden Hierarchy

模拟。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 100005;int n, cnt, lim, siz[MAXN];set <string> chd[MAXN];vector <int> adj[MAXN];map <int, string> rel;map <string, int> idx;bool fil[MAXN];inline void DFS(int x){    for (auto y : adj[x])        DFS(y), siz[x] += siz[y];}inline void Solve(int x){    if (fil[x])        return ;    bool flg = false;    int val = 0;    for (auto y : adj[x])        if (!fil[y])            val = max(val, siz[y]), flg = true;    if (!flg)    {        cout << "  " << rel[x] << " " << siz[x] << endl;        return ;    }    if (val >= lim)    {        cout << "- " << rel[x] << " " << siz[x] << endl;        for (auto c : chd[x])            Solve(idx[c]);        return ;    }    else    {        cout << "+ " << rel[x] << " " << siz[x] << endl;        return ;    }}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)    {        string str, pre;        cin >> str;        idx[str] = ++ cnt, rel[cnt] = str, siz[cnt] = Read(), pre = str, fil[cnt] = true;        for (int i = str.length() - 1; ~i; i --)            if (str[i] == '/')            {                string cur = str.substr(0, i + 1);                if (idx.find(cur) == idx.end())                {                    idx[cur] = ++ cnt, rel[cnt] = cur;                    adj[cnt].pb(cnt - 1), chd[cnt].insert(pre), pre = cur;                }                else                {                    adj[idx[cur]].pb(cnt), chd[idx[cur]].insert(pre);                    break;                }            }    }    lim = Read(), DFS(idx["/"]), Solve(idx["/"]);    return 0;}

Intrinsic Interval

考虑一对相邻的数(pi,pi+1),如果它们选了那么它们之间的数也必须选,求出值域在它们之间的出现位置[l,r],那么让i[l,r)所有点连边。

不难发现最后答案就是这个区间所有点可达点的最小标号和最大标号。

用线段树优化建边和维护查询。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 500005;int n, m, ql, qr, cnt, tot, tim, top, seg_rot, d[MAXN], p[MAXN], q[MAXN], dfn[MAXN], low[MAXN], scc[MAXN], lch[MAXN], rch[MAXN], sta[MAXN], adj_min[MAXN], adj_max[MAXN], seg_min[MAXN], seg_max[MAXN];vector <int> adj[MAXN], adv[MAXN];inline void Modify(int x, int l, int r, int p, int u, int v){    seg_min[x] = min(seg_min[x], u), seg_max[x] = max(seg_max[x], v);    if (l == r)        return ;    int mid = l + r >> 1;    return p <= mid ? Modify(x << 1, l, mid, p, u, v) : Modify(x << 1 | 1, mid + 1, r, p, u, v);}inline pii Query(int x, int l, int r, int ql, int qr){    if (l == ql && r == qr)        return mp(seg_min[x], seg_max[x]);    int mid = l + r >> 1;    if (qr <= mid)        return Query(x << 1, l, mid, ql, qr);    if (ql > mid)        return Query(x << 1 | 1, mid + 1, r, ql, qr);    pii L = Query(x << 1, l, mid, ql, mid), R = Query(x << 1 | 1, mid + 1, r, mid + 1, qr);    return mp(min(L.xx, R.xx), max(L.yy, R.yy));}inline void Build(int &x, int l, int r){    x = ++ tot;    if (l == r)        return (void)(adj[x].pb(l));    int mid = l + r >> 1;    Build(lch[x], l, mid), Build(rch[x], mid + 1, r), adj[x].pb(lch[x]), adj[x].pb(rch[x]);}inline void Addedge(int x, int l, int r, int ql, int qr, int p){    if (l == ql && r == qr)        return (void)(adj[p].pb(x));    int mid = l + r >> 1;    if (qr <= mid)        Addedge(lch[x], l, mid, ql, qr, p);    else if (ql > mid)        Addedge(rch[x], mid + 1, r, ql, qr, p);    else        Addedge(lch[x], l, mid, ql, mid, p), Addedge(rch[x], mid + 1, r, mid + 1, qr, p);}inline void DFS(int x){    dfn[x] = low[x] = ++ tim, sta[++ top] = x;    for (auto y : adj[x])        if (!dfn[y])            DFS(y), low[x] = min(low[x], low[y]);        else if (!scc[y])            low[x] = min(low[x], dfn[y]);    if (dfn[x] == low[x])    {        cnt ++, adj_min[cnt] = n, adj_max[cnt] = 0;        for (int k = 0; k ^ x; )        {            scc[k = sta[top --]] = cnt;            if (k < n)                adj_min[cnt] = min(adj_min[cnt], k), adj_max[cnt] = max(adj_max[cnt], k);        }    }}inline void ReBuild(){    for (int i = 1; i <= tot; i ++)        for (auto j : adj[i])            if (scc[i] ^ scc[j])                adv[scc[i]].pb(scc[j]), d[scc[j]] ++;    for (int i = 1; i <= cnt; i ++)        if (!d[i])            q[++ qr] = i;    while (ql < qr)    {        int x = q[++ ql];        for (auto y : adv[x])            if (!-- d[y])                q[++ qr] = y;    }    for (int i = qr; i; i --)    {        int x = q[i];        for (auto y : adv[x])            adj_min[x] = min(adj_min[x], adj_min[y]), adj_max[x] = max(adj_max[x], adj_max[y]);    }}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), tot = n - 1;    mset(seg_min, 0x3f), mset(seg_max, 0);    for (int i = 1; i <= n; i ++)        p[i] = Read(), Modify(1, 1, n, p[i], i, i);    if (n == 1)    {        m = Read();        while (m --)            puts("1 1");        return 0;    }    Build(seg_rot, 1, n - 1);    for (int i = 1; i < n; i ++)    {        int l = p[i], r = p[i + 1];        if (l > r)            swap(l, r);        pii ret = Query(1, 1, n, l, r);        Addedge(seg_rot, 1, n - 1, ret.xx, ret.yy - 1, i);    }    for (int i = 1; i <= tot; i ++)        if (!dfn[i])            DFS(i);    ReBuild();    mset(seg_min, 0x3f), mset(seg_max, 0);    for (int i = 1; i < n; i ++)        Modify(1, 1, n - 1, i, adj_min[scc[i]], adj_max[scc[i]]);    m = Read();    while (m --)    {        int l = Read(), r = Read();        if (l == r)            printf("%d %d\n", l, r);        else        {            pii ret = Query(1, 1, n - 1, l, r - 1);            printf("%d %d\n", ret.xx, ret.yy + 1);        }    }    return 0;}

Justified Jungle

暴力。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 1000005;int n, siz[MAXN], cnt[MAXN];vector <int> fac, ans, adj[MAXN];inline void DFS(int x, int p){    siz[x] = 1;    for (auto y : adj[x])        if (y ^ p)            DFS(y, x), siz[x] += siz[y];    if (x ^ 1)        cnt[__gcd(siz[x], n)] ++;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i < n; i ++)        if (n % i == 0)            fac.pb(i);    for (int i = 1, x, y; i < n; i ++)        x = Read(), y = Read(), adj[x].pb(y), adj[y].pb(x);    DFS(1, 0);    for (int i = 0; i < fac.size(); i ++)        for (int j = i + 1; j < fac.size(); j ++)           if (fac[j] % fac[i] == 0)               cnt[fac[i]] += cnt[fac[j]];    for (auto x : fac)        if (cnt[x] == n / x - 1)            ans.pb(n / x - 1);    reverse(ans.begin(), ans.end());    for (auto x : ans)        printf("%d ", x);    putchar(10);    return 0;}

Kitchen Knobs

首先去掉所有位置都是相同数字的,然后差分,每次操作相当于某个位置加x,另一个位置减x

不难转化成:将所有数分成尽量多组,满足每组和为0,答案是n减去组数。

贪心之后只有三种数了,暴力DP即可。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 505;int n, b[MAXN], cnt[7], f[MAXN][MAXN][7], g[MAXN][MAXN][7];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)    {        int a[7];        a[0] = Read();        for (int j = 1; j < 7; j ++)            a[j] = a[j - 1] / 10 + a[j - 1] % 10 * 1000000;        if (a[0] == a[1])            i --, n --;        else            b[i] = max_element(a, a + 7) - a;    }    for (int i = 1; i <= n + 1; i ++)        cnt[(b[i] - b[i - 1] + 7) % 7] ++;    int ret = n + 1 - cnt[0];    for (int i = 1, v; i < 4; i ++)        v = min(cnt[i], cnt[7 - i]), ret -= v, cnt[i] -= v, cnt[7 - i] -= v;    int x = cnt[1] ? 1 : 6, cx = cnt[1] ? cnt[1] : cnt[6], y = cnt[2] ? 2 : 5, cy = cnt[2] ? cnt[2] : cnt[5], z = cnt[3] ? 3 : 4, cz = cnt[3] ? cnt[3] : cnt[4];    for (int i = 0; i <= cy; i ++)        for (int j = 0; j <= cz; j ++)            for (int k = 0; k < 7; k ++)                f[i][j][k] = -1;    f[0][0][0] = 0;    for (int l = 0; l <= cx; l ++)    {        for (int i = 0; i <= cy; i ++)            for (int j = 0; j <= cz; j ++)                for (int k = 0; k < 7; k ++)                    g[i][j][k] = f[i][j][k], f[i][j][k] = -1;        for (int i = 0; i <= cy; i ++)            for (int j = 0; j <= cz; j ++)                for (int k = 0; k < 7; k ++)                    if (~g[i][j][k])                    {                        if (l < cx)                            f[i][j][(k + x) % 7] = max(f[i][j][(k + x) % 7], g[i][j][k] + ((k + x) % 7 == 0));                        if (i < cy)                            g[i + 1][j][(k + y) % 7] = max(g[i + 1][j][(k + y) % 7], g[i][j][k] + ((k + y) % 7 == 0));                        if (j < cz)                            g[i][j + 1][(k + z) % 7] = max(g[i][j + 1][(k + z) % 7], g[i][j][k] + ((k + z) % 7 == 0));                    }    }    return printf("%d\n", ret - g[cy][cz][0]), 0;}

Lunar Landscape

前缀和。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 3005;const int N = 3002;int n, a[MAXN][MAXN], b[MAXN][MAXN];double ans;int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)    {        char opt[2];        scanf("%s", opt);        int x = Read(), y = Read(), z = Read();        if (opt[0] == 'A')            x += N / 2 - z / 2, y += N / 2 - z / 2, a[x][y] = max(a[x][y], z);        else            x += N / 2 - z / 2, y += N / 2, b[x][y] = max(b[x][y], z);    }    for (int i = 1; i <= N; i ++)        for (int j = 1; j <= N; j ++)            a[i][j] = max(max(a[i][j], a[i - 1][j - 1] - 1), max(a[i - 1][j] - 1, a[i][j - 1] - 1)), b[i][j] = max(max(b[i][j], b[i - 1][j] - 1), max(b[i - 1][j - 1] - 2, b[i - 1][j + 1] - 2));    for (int i = 1; i <= N; i ++)        for (int j = 1; j <= N; j ++)            if (a[i][j])                ans ++;            else            {                if (b[i][j])                    ans += 0.25;                if (b[i][j + 1])                    ans += 0.25;                if (b[i][j] > 1 || b[i][j + 1] > 1)                    ans += 0.25;                if (b[i - 1][j] > 1 || b[i - 1][j + 1] > 1)                    ans += 0.25;            }    return printf("%.2lf\n", ans), 0;}