CodeForces Gym 101190简要题解

来源:互联网 发布:电脑卸载软件推荐 编辑:程序博客网 时间:2024/06/05 10:25

NEERC天天被搬还是做了好了。

Abbreviation

模拟。

#define FIO "abbreviation"#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, p[MAXN];string t[MAXN];char s[MAXN];inline bool In(int x, int l, int r){    return x >= l && x <= r;}inline int Find(int x){    if (!In(s[x], 'A', 'Z') || !In(s[x + 1], 'a', 'z'))        return 0;    for (x ++; In(s[x], 'a', 'z'); x ++);    if (In(s[x], 'A', 'Z'))        return 0;    return x;}inline int Chk(int x){    int y, z;    if (!(y = Find(x)) || s[y] != ' ' || !(z = Find(y + 1)))        return 0;    t[x] += s[x], t[x] += s[y + 1];    while (true)    {        if (s[z] != ' ' || !(y = Find(z + 1)))            return z - 1;        t[x] += s[z + 1];        z = y;    }}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    for (char c = getchar(); ~c; c = getchar())        s[++ n] = c;    for (int i = 1, j; i <= n; i ++)        if (!In(s[i - 1], 'A', 'Z') && !In(s[i - 1], 'a', 'z'))            if (j = Chk(i))                p[i] = 1, p[j] = 2, i = j;    for (int i = 1; i <= n; i ++)    {        if (p[i] == 1)            printf("%s (", t[i].c_str());        putchar(s[i]);        if (p[i] == 2)            putchar(')');    }}

Binary Code

暴力是枚举两个点的两种状态,看是否一个是另一个的前缀,跑2-SAT。
考虑用trie树优化建边,分别是前缀和和后缀和(表示选没选)。

#define FIO "binary"#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;const int MAXM = 4000005;int n, tot, len, cnt, num, scc[MAXM], par[MAXN], pos[MAXN], st[MAXN], ed[MAXN], tst[MAXN], ted[MAXN], dfn[MAXM], nxt[MAXN][2];vector <int> adj[MAXM], vec[MAXN], G[MAXM];char s[MAXN], ch[MAXN];bool res[MAXN];inline void Add(int p){    int cur = 0;    for (int i = 1; i <= len; cur = nxt[cur][s[i ++] - '0'])        if (!nxt[cur][s[i] - '0'])            par[nxt[cur][s[i] - '0'] = ++ cnt] = cur;    pos[p] = cur;    vec[cur].pb(p);}inline void Build(){    for (int i = 1; i <= cnt; i ++)        if (!vec[i].empty())        {            for (int j = 0; j < vec[i].size(); j ++)                if (!j)                    adj[++ tot].pb(vec[i][j] ^ 1);                else                    adj[vec[i][j]].pb(tot), adj[tot + 1].pb(tot), adj[++ tot].pb(vec[i][j] ^ 1);            tst[i] = tot;            for (int j = 0; j < vec[i].size(); j ++)                if (!j)                    adj[vec[i][j]].pb(++ tot);                else                    adj[tot].pb(vec[i][j] ^ 1), adj[tot].pb(tot + 1), adj[vec[i][j]].pb(++ tot);            ted[i] = tot;        }    for (int i = 2; i <= (n << 1 | 1); i ++)        for (int j = par[pos[i]]; j; j = par[j])            if (!vec[j].empty())                adj[i].pb(tst[j]), adj[ted[j]].pb(i ^ 1);}int sta[MAXM], low[MAXM], tim, tp;inline void Dfs(int x){    dfn[x] = low[x] = ++ tim;    sta[++ tp] = 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])    {        int cur = 0; num ++;        while (cur ^ x)            scc[cur = sta[tp --]] = num;    }}int vis[MAXM], opp[MAXM], deg[MAXM], q[MAXM], ql, qr;inline void Print(){    for (int i = 1; i <= n; i ++)        opp[scc[i << 1]] = scc[i << 1 | 1], opp[scc[i << 1 | 1]] = scc[i << 1];    for (int x = 2; x <= tot; x ++)        for (auto y : adj[x])            if (scc[x] ^ scc[y])                G[scc[y]].pb(scc[x]), deg[scc[x]] ++;    for (int i = 1; i <= num; i ++)        if (!deg[i])            q[++ qr] = i;    while (ql ^ qr)    {        int x = q[++ ql];        if (!vis[x])             vis[x] = 1, vis[opp[x]] = -1;        for (auto y : G[x])            if (!-- deg[y])                q[++ qr] = y;    }    for (int i = 2; i <= (n << 1 | 1); i ++)        if (~vis[scc[i]])            res[i >> 1] = i & 1;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    n = Read(), tot = n << 1 | 1;    for (int i = 1, t = 1; i <= n; i ++)    {        scanf("%s", s + 1), len = strlen(s + 1);        st[i] = t;        for (int j = 1; j <= len; j ++)            ch[t ++] = s[j];        ed[i] = t;        for (int j = 1; j <= len; j ++)            if (s[j] == '?')            {                s[j] = '0', Add(i << 1);                s[j] = '1', Add(i << 1 | 1);                break;            }            else if (j == len)                Add(i << 1), Add(i << 1 | 1);    }    Build();    for (int i = 2; i <= tot; i ++)        if (!dfn[i])            Dfs(i);    for (int i = 1; i <= n; i ++)        if (scc[i << 1] == scc[i << 1 | 1])            return puts("NO"), 0;    puts("YES");    Print();    for (int i = 1; i <= n; putchar(10), i ++)        for (int j = st[i]; j < ed[i]; j ++)            if (ch[j] == '?')                putchar(res[i] + '0');            else                putchar(ch[j]);    return 0;}

Cactus Construction

先把所有环和桥边分开,然后随便构造一下就好了。
详见代码。

#define FIO "cactus"#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 = 50005;struct Node{    int opt, a, b, c;    Node(int _opt = 0, int _a = 0, int _b = 0, int _c = 0)    {        opt = _opt, a = _a, b = _b, c = _c;    }};int n, m, tim, cnt, par[MAXN], a[MAXN], dfn[MAXN];vector <int> adj[MAXN], hav[MAXN], cir[MAXN];vector <Node> ans;bool f[MAXN];inline void Dfs(int x){    dfn[x] = ++ tim;    for (auto y : adj[x])        if (y ^ par[x])            if (!dfn[y])                par[y] = x, Dfs(y);            else if (dfn[y] < dfn[x])            {                hav[y].pb(++ cnt);                cir[cnt].pb(y);                for (int i = x; i ^ y; i = par[i])                    cir[cnt].pb(i);            }}inline void Solve(int x){    for (auto c : hav[x])    {        for (auto y : cir[c])            if (y ^ x)                f[y] = 1;        for (auto y : cir[c])            if (y ^ x)                Solve(y);        for (int i = 1; i < cir[c].size(); i ++)        {            int p = cir[c][i - 1], q = cir[c][i];            ans.pb(Node(2, p, 1, 3));            ans.pb(Node(1, p, q));            ans.pb(Node(3, p, 1, 3));            ans.pb(Node(2, p, 3, i == 1 ? 4 : 2));        }        int y = cir[c].back();        ans.pb(Node(3, x, 1, 4));        ans.pb(Node(2, x, 1, 2));        ans.pb(Node(2, x, 4, 1));    }    for (auto y : adj[x])        if (!f[y])        {            f[y] = 1, Solve(y);            ans.pb(Node(2, y, 1, 3));            ans.pb(Node(1, x, y));            ans.pb(Node(3, x, 1, 3));            ans.pb(Node(2, x, 3, 2));        }}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    n = Read(), m = Read();    while (m --)    {        int x = Read();        for (int i = 1; i <= x; i ++)            a[i] = Read();        for (int i = 1; i < x; i ++)            adj[a[i]].pb(a[i + 1]), adj[a[i + 1]].pb(a[i]);    }    Dfs(1);    f[1] = 1;    Solve(1);    printf("%d\n", ans.size());    for (auto e : ans)        if (e.opt == 1)            printf("j %d %d\n", e.a, e.b);        else if (e.opt == 2)            printf("r %d %d %d\n", e.a, e.b, e.c);        else if (e.opt == 3)            printf("c %d %d %d\n", e.a, e.b, e.c);}

Delight for a Cat

考虑费用流,一个点如果选择睡觉那就会影响之后的k个东西,直接跳k步,否则直接走到i+1,求一个流量为max的流即可。

#define FIO "delight"#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 = 1005;const int MAXM = 6005;const int INF = 0x3f3f3f3f;namespace Flow{    struct edge    {        int p, v, w, c;    } e[MAXM];    int V, S, T, hed[MAXN], e_cnt = 1;    LL ans, dis[MAXN];    bool vis[MAXN];    inline void Init(int n)    {        V = n, e_cnt = 1;        for (int i = 0; i < V; i ++)            hed[i] = 0;    }    inline void Add(int x, int y, int w, int c) { e[++ e_cnt] = {y, hed[x], w, c}; hed[x] = e_cnt; }    inline void Addedge(int x, int y, int w, int c) { Add(x, y, w, c); Add(y, x, 0, -c); }    inline bool Spfa()    {        for (int i = 0; i < V; i ++)            dis[i] = 1LL << 60, vis[i] = 0;        queue <int> q;        dis[S] = 0; q.push(S);        while (!q.empty())        {            int x = q.front(); q.pop(); vis[x] = 0;            for (int i = hed[x]; i; i = e[i].v)                if (e[i].w && dis[e[i].p] > dis[x] + e[i].c)                {                    dis[e[i].p] = dis[x] + e[i].c;                    if (!vis[e[i].p])                        vis[e[i].p] = 1, q.push(e[i].p);                }        }        return dis[T] < 1LL << 60;    }    inline int Dfs(int x, int f)    {        vis[x] = 1;        if (x == T)            return f;        int ret = 0, d;        for (int i = hed[x]; i; i = e[i].v)            if (e[i].w && dis[e[i].p] == dis[x] + e[i].c && !vis[e[i].p])            {                d = Dfs(e[i].p, min(f - ret, e[i].w));                e[i].w -= d; e[i ^ 1].w += d; ret += d;                if (ret == f)                    return ret;            }        return ret;    }    inline int Solve()    {        int ret = 0;        while (Spfa())        {            vis[T] = 1;            while (vis[T])            {                for (int i = 0; i < V; i ++)                    vis[i] = 0;                int d = Dfs(S, INF);                ret += d; ans += d * dis[T];            }        }        return ret;    }}int n, k, p, q, a[MAXN];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    using namespace Flow;    n = Read(), k = Read(), p = k - Read(), q = Read();    Flow::Init(n + 3), Flow::T = n + 2;    for (int i = 1; i <= n; i ++)        a[i] -= Read(), ans += a[i];    for (int i = 1; i <= n; i ++)        a[i] += Read();    for (int i = 1; i <= n; i ++)        Addedge(i, i + k <= n ? i + k : T, 1, -a[i]);    for (int i = 1; i <= n; i ++)        Addedge(i, i == n ? T : i + 1, p - q, 0);    for (int i = 1; i <= k; i ++)        Addedge(n + 1, i, INF, 0);    Addedge(S, n + 1, p, 0);    Solve();    printf("%lld\n", -ans);    for (int i = 1; i <= n; i ++)        putchar(e[i << 1].w ? 'S' : 'E');    putchar(10);    return 0;}

Expect to Wait

随便推一推发现是个一次函数的形式,离线之后打上差分标记。

#define FIO "expect"#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, m, t[MAXN], c[MAXN], l[MAXN];LL p, q, a[MAXN], b[MAXN], ans[MAXN];pii e[MAXN];char ch[2];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    n = Read(), m = Read();    for (int i = 1, x, y; i <= n; i ++)    {        scanf("%s", ch);        if (ch[0] == '+')            t[i] = Read(), c[i] = Read();        else            t[i] = Read(), c[i] = -Read();    }    for (int i = 1; i <= m; i ++)        e[i].xx = Read(), e[i].yy = i;    sort(e + 1, e + m + 1);    for (int i = 1; i <= m; i ++)        l[i] = e[i].xx;    for (int i = 1, s = 0, d; i <= n; i ++)    {        s += c[i], d = t[i + 1] - t[i];        if (s < 0)        {            int p = lower_bound(l + 1, l + m + 1, -s) - l;            if (i ^ n)                a[0] -= d, b[0] -= 1LL * d * s, a[p] += d, b[p] += 1LL * d * s;            else                for (int j = 1; j < p; j ++)                    ans[e[j].yy] = -1;        }    }    for (int i = 0; i <= m; i ++)    {        p += a[i], q += b[i];        if (~ans[e[i].yy])            ans[e[i].yy] = p * e[i].xx + q;    }    for (int i = 1; i <= m; i ++)        if (ans[i] == -1)            puts("INFINITY");        else            printf("%lld\n", ans[i]);    return 0;}

Foreign Postcards

暴力想法是枚举一对(i,j),然后用个后缀和来优化一下。

#define FIO "foreign"#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;long double ans;int n, a[MAXN];LL p, q, c, d;char s[MAXN];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    scanf("%s", s + 1); n = strlen(s + 1);    for (int i = 1; i <= n; i ++)        a[i] = s[i] == 'W';    for (int i = 1; i <= n; i ++)        c += a[i], d += !a[i], p += c, q += d;    for (int i = 0; i < n; i ++)    {        double r = i ? 1.0 / (1LL * (n - i) * (n - i + 1)) : 1.0 / n;        ans += r * (a[i + 1] ? q : p);        p -= a[i + 1] * (n - i);        q -= (!a[i + 1]) * (n - i);    }    return printf("%.10Lf\n", ans), 0;}

Game on Graph

考虑记f(i,j)表示当前在i,第j个人行动,是否游戏会结束,g(i,j)表示游戏是否会让A(第一目标是赢的那个人)获胜,然后倒着递推。

#define FIO "game"#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;vector <int> adj[MAXN], rev[MAXN];bool a[MAXN][2], b[MAXN][2];int n, m, ql, qr, d[MAXN];pii q[MAXN << 1];inline void Solve(bool f[MAXN][2]){    ql = qr = 0;    for (int i = 1; i <= n; i ++)        for (int j = 0; j < 2; j ++)            if (f[i][j])                q[++ qr] = mp(i, j);    for (int i = 1; i <= n; i ++)        d[i] = adj[i].size();    while (ql ^ qr)    {        int x = q[++ ql].xx, p = q[ql].yy;        if (p)        {            for (auto y : rev[x])                if (!f[y][0] && !-- d[y])                    f[y][0] = 1, q[++ qr] = mp(y, 0);        }        else            for (auto y : rev[x])                if (!f[y][1])                    f[y][1] = 1, q[++ qr] = mp(y, 1);    }}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    n = Read(), m = Read();    for (int i = 1, x, y; i <= m; i ++)        x = Read(), y = Read(), adj[x].pb(y), rev[y].pb(x);    for (int i = 1; i <= n; i ++)        if (adj[i].empty())            a[i][0] = a[i][1] = b[i][0] = 1;    Solve(a);    Solve(b);    for (int i = 1; i <= n; i ++)        if (b[i][0])            putchar('L');        else if (!a[i][0])            putchar('D');        else            putchar('W');    putchar(10);    for (int i = 1; i <= n; i ++)        if (b[i][1])            putchar('W');        else if (a[i][1])            putchar('L');        else            putchar('D');    putchar(10);    return 0;}

Hard Refactoring

模拟。

#define FIO "hard"#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 a[MAXN], n = 1 << 15;vector <pii> ans;char s[MAXN];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    while (fgets(s, MAXN, stdin))    {        int l, r;        if (sscanf(s, "x >= %d && x <= %d", &l, &r) ^ 2)            if (sscanf(s, "x >= %d", &l) ^ 1)                sscanf(s, "x <= %d", &r), l = -n;            else                r = n - 1;        if (l > r)            continue;        a[l + n] ++, a[r + n + 1] --;    }    for (int i = 1; i < MAXN; i ++)        a[i] += a[i - 1];    for (int i = 0; i < MAXN; i ++)        if (a[i])        {            int p = i;            while (a[p + 1])                p ++;            ans.pb(mp(i - n, p - n));            i = p;        }    if (ans.empty())        return puts("false"), 0;    if (ans.size() == 1 && ans[0].xx == -n && ans[0].yy == n - 1)        return puts("true"), 0;    for (int i = 0; i < ans.size(); i ++)    {        pii x = ans[i];        if (x.xx == -n)            printf("x <= %d", x.yy);        else if (x.yy == n - 1)            printf("x >= %d", x.xx);        else            printf("x >= %d && x <= %d", x.xx, x.yy);        if (i < ans.size() - 1)            puts(" ||");    }    putchar(10);    return 0;}

Indiana Jones and the Uniform Cave

挺厉害的交互题。
考虑用DFSL表示不在栈中的点,R表示在栈中的点,C表示没经过的点。
如果一个点走到了不在栈中的点,那么我们先向上跳(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;}int n, m, L = 0, R = 1, C = 2, adj[25][25];inline int Next(){    char s[15];    scanf("%s", s);    if (s[0] == 'l')        return L;    if (s[0] == 'r')        return R;    if (s[0] == 'c')        return C;    exit(0);}inline int Print(int p, int t, int v){    printf("%d %s %d\n", p, t ? "right" : "left", v);    fflush(stdout);    return Next();}inline void Dfs(int x, int dep){    for (int i = 0; i < m; i ++)    {        int val = Print(1, R, 1), cnt = 0;        if (val == C)            Dfs(++ n, adj[x][i] = dep + 1), val = L;        if (val == L)        {            for (; Print(0, L, 0) == L; );            for (; Print(0, R, 0) == R; cnt ++);            for (; Print(0, L, 0) == L; );            for (int i = 1; i <= cnt; i ++)                Print(0, R, 0);            adj[x][i] = dep - cnt;        }        else        {            for (; Print(0, L, 0) == R; cnt ++);            for (int i = 0; i <= cnt; i ++)                Print(0, R, 0);            for (int i = 1; i <= cnt; i ++)                Print(0, R, 0);            adj[x][i] = dep - cnt;        }    }    if (x ^ 1)    {        int pos = -1, val;        for (int i = 0; i < m; i ++)            if (!~pos || adj[x][i] < adj[x][pos])                pos = i;        val = Print((pos + 1) % m, L, (pos + 1) % m);        for (; val == L; val = Print(0, L, 0));        for (; Print(0, R, 0) == R; );    }}int main(){    m = Read();    Next();    Dfs(++ n, 1);    return 0;}

Jenga Boom

暴力。

#define FIO "jenga"#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 = 5005;int n, m, h, w, l[MAXN], r[MAXN], c[MAXN], s[MAXN];bool f[MAXN][MAXN << 1];inline bool chk(){    LL cnt[2] = {0, 0}, sum[2] = {0, 0};    for (int i = h, cur = i & 1; i > 1; i --, cur ^= 1)    {        cnt[cur] += c[i], sum[cur] += s[i];        if ((sum[cur ^ 1] + cnt[cur] * n) <= (cnt[0] + cnt[1]) * (l[i - 1] * 2 - 2))            return 1;        if ((sum[cur ^ 1] + cnt[cur] * n) >= (cnt[0] + cnt[1]) * (r[i - 1] * 2))            return 1;    }    return 0;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    n = Read(), w = Read(), h = Read(), m = Read();    for (int i = 1; i <= h; i ++)        l[i] = 1, r[i] = n, c[i] = n, s[i] = n * n;    for (int i = 1; i <= m; i ++)    {        int x = Read(), y = Read();        f[x][y] = 1;        s[x] -= y * 2 - 1;        if (-- c[x])        {            while (f[x][l[x]])                l[x] ++;            while (f[x][r[x]])                r[x] --;        }        else if (x == h)            h --;        else            return printf("yes\n%d\n", i), 0;        if (chk())            return printf("yes\n%d\n", i), 0;    }    return puts("no"), 0;}

Kids Designing Kids

三个图异或为0,那么左上角一定有两个能匹配,枚举一下3种情况验证就好了。

#define FIO "kids"#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;}set <pii> A, B, C;pii a, b, c;char ch[1005];inline void Init(set <pii> &S, pii &s){    int n = Read(), m = Read(), f = 0;    for (int i = 1; i <= n; i ++)    {        scanf("%s", ch + 1);        for (int j = 1; j <= m; j ++)            if (ch[j] == '*')            {                if (!f)                    f = 1, s = mp(-i, -j);                S.insert(mp(i + s.xx, j + s.yy));            }    }}inline bool Chk(set <pii> &A, pii &a, set <pii> &B, pii &b, set <pii> &C, pii &c){    set <pii> S;    for (auto x : A)        S.insert(x);    for (auto x : B)        if (S.find(x) != S.end())            S.erase(x);        else            S.insert(x);    if (S.size() != C.size())        return 0;    pii s = *S.begin();    for (auto x : C)        if (S.find(mp(x.xx + s.xx, x.yy + s.yy)) == S.end())            return 0;    c = mp(c.xx + s.xx, c.yy + s.yy);    return 1;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    Init(A, a); Init(B, b); Init(C, c);    if (Chk(A, a, B, b, C, c) || Chk(A, a, C, c, B, b) || Chk(B, b, C, c, A, a))        return printf("YES\n%d %d\n", b.yy - a.yy, b.xx - a.xx), 0;    return puts("NO"), 0;}

List of Primes

注意到最后质数不会很大,预处理每个质数的贡献就可以开始爆搜了。

#define FIO "list"#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 = 2340;LL f[MAXN][MAXN], g[MAXN][MAXN], l, r;int n, cnt, now, p[MAXN], v[MAXN], use[MAXN];bool chk[MAXN];char ch[MAXN];inline void Init(){    for (int i = 2; i < MAXN; i ++)    {        if (!chk[i])            p[++ n] = i;        for (int j = 1; i * p[j] < MAXN; j ++)        {            chk[i * p[j]] = 1;            if (i % p[j] == 0)                break;        }    }}inline void Print(LL l, LL r){    int tot = 0, cur;    ch[++ tot] = '[';    for (int i = 1, t; i <= cnt; i ++)    {        t = p[use[i]], cur = tot + v[use[i]];        while (t)            ch[cur --] = t % 10 + '0', t /= 10;        tot += v[use[i]];        ch[++ tot] = ',', ch[++ tot] = ' ';    }    ch[-- tot] = ']', ch[++ tot] = ',', ch[++ tot] = ' ';    for (LL i = l; i <= min(r, (LL)tot); i ++)        putchar(ch[i]);}inline void Dfs(int sum, LL l, LL r){    int i;    for (i = use[cnt] + 1; i <= n && p[i] < sum; i ++)    {        LL t = f[sum - p[i]][i + 1] * (now + v[i] + 2) + g[sum - p[i]][i + 1];        if (t < l)            l -= t, r -= t;        else        {            use[++ cnt] = i, now += v[i] + 2;            Dfs(sum - p[i], l, r);            cnt --, now -= v[i] + 2;            l = 1, r -= t;            if (r <= 0)                return ;        }    }    if (p[i] == sum)        use[++ cnt] = i, Print(l, r), cnt --;    return ;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    cin >> l >> r;    Init();    for (int i = 1; i <= n; i ++)        v[i] = p[i] >= 1000 ? 4 : (p[i] >= 100 ? 3 : (p[i] >= 10 ? 2 : 1)), f[p[i]][i] = 1, g[p[i]][i] = v[i] + 4;    for (int i = 2; i < MAXN; i ++)        for (int j = n; j; j --)        {            f[i][j] += f[i][j + 1];            g[i][j] += g[i][j + 1];            if (i >= p[j])                f[i][j] += f[i - p[j]][j + 1], g[i][j] += g[i - p[j]][j + 1] + f[i - p[j]][j + 1] * (v[j] + 2);        }    for (int i = 2; i < MAXN; i ++)    {        if (g[i][1] < l)            l -= g[i][1], r -= g[i][1];        else        {            Dfs(i, l, r);            l = 1, r -= g[i][1];            if (r <= 0)                return 0;        }    }}

Mole Tunnels

暴力是费用流。
完全二叉树深度是log的,模拟一下费用流就好了。

#define FIO "mole"#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;int n, m, c[MAXN], f[MAXN], g[MAXN], h[MAXN], p[MAXN], ans;inline void Upd(int x){    f[x] = 1 << 30, p[x] = 0;    if (c[x])        f[x] = 0, p[x] = x;    if ((x << 1) <= n && f[x] > f[x << 1] + (h[x << 1] ? -1 : 1))        f[x] = f[x << 1] + (h[x << 1] ? -1 : 1), p[x] = p[x << 1];    if ((x << 1 | 1) <= n && f[x] > f[x << 1 | 1] + (h[x << 1 | 1] ? -1 : 1))        f[x] = f[x << 1 | 1] + (h[x << 1 | 1] ? -1 : 1), p[x] = p[x << 1 | 1];}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#else    freopen(FIO".in", "r", stdin);    freopen(FIO".out", "w", stdout);#endif    n = Read(), m = Read();    for (int i = 1; i <= n; i ++)        c[i] = Read();    for (int i = n; i; i --)        Upd(i);    while (m --)    {        int x = Read(), y, l, cur = 0, ret = 1 << 30;        for (int i = x; i; cur += g[i] ? -1 : 1, i >>= 1)            if (f[i] + cur < ret)                ret = f[i] + cur, l = i;        c[y = p[l]] --;        for (int i = x; i ^ l; i >>= 1)            if (g[i])                g[i] --;            else                h[i] ++;        for (int i = y; i ^ l; i >>= 1)            if (h[i])                h[i] --;            else                g[i] ++;        for (int i = x; i; i >>= 1)            Upd(i);        for (int i = y; i; i >>= 1)            Upd(i);        printf("%d\n", ans += ret);    }}
原创粉丝点击