学校の訓練2019年9月22日

概要

私はどんな感情を持っていません。

唯一の難点は、それまでこのUSACOプラチナのでしょうもないNOIPのアイデアです。

これは完全に参照するには問題ありませんでした時間を持って、実際にゲームをシミュレートすることは困難ではない私にチューニングされたコードの低レベルのほか、NOIPを反映しています。

選挙区

トピックポータル

http://192.168.21.187/contest/30/problem/1

http://47.100.137.146/contest/30/problem/1

問題の解決策

\(H \)として\(1 \)、\ (G \)\( - 1 \) だから、ピースとあれば\(> 0 \)あなたが価格を支払う必要はありません、との一枚あれば\(<0 \)を支払うことを要求される(\ 1)\価格。

オーダー\(DPは[I] \)フロントある\(Iは\)牛への最小の損傷番目、\(S_I \)は、元の接頭文字列を表し、明らか式DPすることができます。
\ [Dpは[I] = \
MIN_ {J = I-K + 1} ^ {I-1} DP [J] + [s_j \ GEQ S_I] \] 類似bzoj3831 [Poi2014]リトルバード実際、我々のみそれは必要です\(DP [j]を、s_j \) このタプルはそれを単調にキューを確立します。

私は、セグメントツリーの半分しか考えてそうすることができるので、私たちは、単にツリーラインが終わっ直接書いたテストので。したがって、次のセグメントツリーである\(O(Nログn \ )\) 各ノードのコードセグメントツリーは単調キュー維持します。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

#define lc o << 1
#define rc o << 1 | 1

const int N = 3e5 + 7;
const int INF = 0x3f3f3f3f;

int n, m, T;
int s[N], dp[N];
char a[N];

struct Node {
    std::vector<int> q;
    int hd, tl;
} t[N << 3];

inline void build(int o, int L, int R) {
    t[o].hd = 1, t[o].tl = 0, t[o].q.pb(0);
    if (L == R) return;
    int M = (L + R) >> 1;
    build(lc, L, M), build(rc, M + 1, R);
}
inline void ins(int o, int L, int R, int x, int k) {
    while (t[o].hd <= t[o].tl && dp[k] <= dp[t[o].q[t[o].tl]]) --t[o].tl, t[o].q.pop_back();
    t[o].q.push_back(k), ++t[o].tl;
    if (L == R) return;
    int M = (L + R) >> 1;
    if (x <= M) ins(lc, L, M, x, k);
    else ins(rc, M + 1, R, x, k);
}
inline int qmin(int o, int L, int R, int l, int r, int k) {
    if (l > r) return INF;
    if (l <= L && R <= r) {
        while (t[o].hd <= t[o].tl && t[o].q[t[o].hd] < k - m) ++t[o].hd;
        if (t[o].hd > t[o].tl) return INF;
        else return dp[t[o].q[t[o].hd]];
    }
    int M = (L + R) >> 1;
    if (r <= M) return qmin(lc, L, M, l, r, k);
    if (l > M) return qmin(rc, M + 1, R, l, r, k);
    return std::min(qmin(lc, L, M, l, r, k), qmin(rc, M + 1, R, l, r, k));
}

inline void work() {
    build(1, 0, n << 1);
    ins(1, 0, n << 1, n, 0);
    for (int i = 1; i <= n; ++i) {
        dp[i] = std::min(qmin(1, 0, n << 1, 0, n + s[i] - 1, i), qmin(1, 0, n << 1, n + s[i], n << 1, i) + 1);
        ins(1, 0, n << 1, n + s[i], i);
    }
    printf("%d\n", dp[n]);
}

inline void init() {
    scanf("%d%d%s", &n, &m, a + 1);
    for (int i = 1; i <= n; ++i) s[i] = s[i - 1] + (a[i] == 'H' ? 1 : -1);
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#else
    File(redistricting);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

運動

トピックポータル

http://192.168.21.187/contest/30/problem/2

http://47.100.137.146/contest/30/problem/2

問題の解決策

我々が型破りルートパスカバーとして見られるそれぞれを取る場合、2つのパスがより交通をカバー又はケースの側面に等しくなければならない件名の要件を満たすため、見つけるのは簡単です。

そのような解決策を見つける方法を考えてみましょう。

点のために、我々は見つけることができる\(F1 [X] \)どのように多くのパスに含まれている\(X \)サブツリー、(\ F2 [X-])\エンドポイントパスの数が存在することです中\(X \)サブツリー。そう\(SS [X] = F2 [X] - F1 [X] \) でエンドポイントのパスのどの程度を示すことができる\(X \)サブツリー、スルー(X \)\バックにX(\ \)外のサブツリー。\(GG [X]が\)何からのパスを示して\(X \)を介して、サブツリーのうち(X \)\バックに\(FA [X] \)自体又は\(FA [X] \)別のサブツリー。

元の質問に、のために\(UはLCAのに\に\のV \) そのようなパス、それはパスの数は、エッジと重なる有します。すべての可能なカウントまず考えてみて、その後、違法削除。全ての可能性のある、全てのエンドポイントの存在下であるべきである\(LCA \) パスサブツリーすなわち\(F2 [LCA] \)

除去し、そこにあるべきである\(U \へのLCA \へのV \) 上の各点の\(X \) (FA [X] \)\\(LCA \)とエンドポイントが存在しない(\ X \)このことができる経路F1 [FA] -f1 [(\ -GG X] [X] \) 図。しかしため\(X \ LCAの\へ)に最も近いパス上の\(LCAの\)ポイント\(XXの\)と点の同様の定義で\(YYの\) むしろ特別なことは、除去されます\(FA [XX] \)\(LCA \)と端末の不在下で\(XX \)としないで\(YYの\)パス、そこから\(LCA \)サブツリーのうち始点ではない\(XX \)または\(YYの\)パスサブツリーは、これら二つを使用することができます\(F1 [P] - F1 [XX] - F1 [YY] - GG [XX] - GG [YY] + MP [XX、YY] +(SS [P] - SS [XX] - SS [YY] + GG [XX] + GG [YY ])\) 表現です。前記\(MP(X、Y) \) を表し、\は、(X \) アウトサブツリーに(\ FA [X])を\次いで行っ\(Y \)サブツリー内のパスの数を。

最後に、あなた自身を含むべき計算パスの数は、あなたがする必要があります\(--1 \) 2つのパスの各々を計算するための加算後、によって分割される\(2 \)

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

const int N = 2e5 + 7;

int n, m, dfc;
int siz[N], f[N], dep[N], son[N], dfn[N], pre[N], top[N];
int f1[N], f2[N], ss[N], dis[N], gg[N];
std::map<pii, int> mp;

struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }

struct Trail { int x, y, p, xx, yy; } a[N];

inline void dfs1(int x, int fa = 0) {
    dep[x] = dep[fa] + 1, f[x] = fa, siz[x] = 1;
    for fec(i, x, y) if (y != fa) dfs1(y, x), siz[x] += siz[y], siz[y] >= siz[son[x]] && (son[x] = y);
}
inline void dfs2(int x, int pa) {
    top[x] = pa, dfn[x] = ++dfc, pre[dfc] = x;
    if (!son[x]) return; dfs2(son[x], pa);
    for fec(i, x, y) if (y != son[x] && y != f[x]) dfs2(y, y);
}
inline int lca(int x, int y) {
    while (top[x] != top[y]) dep[top[x]] > dep[top[y]] ? x = f[top[x]] : y = f[top[y]];
    return dep[x] < dep[y] ? x : y;
}
inline int gson(int x, int p) {
    int d = 0;
    while (top[x] != top[p]) d = top[x], x = f[d];
    return x != p ? son[p] : d;
}

inline void dfs3(int x, int fa = 0) {
    for fec(i, x, y) if (y != fa)
        dfs3(y, x), f1[x] += f1[y], f2[x] += f2[y];
    ss[x] = f2[x] - f1[x];
}
inline void dfs4(int x, int fa = 0) {
    if (fa) dis[x] = dis[fa] + f1[fa] - f1[x] - gg[x];
    for fec(i, x, y) if (y != fa) dfs4(y, x);
}

inline void work() {
    dfs1(1), dfs2(1, 1);
    for (int i = 1; i <= m; ++i) {
        const int &x = a[i].x, &y = a[i].y;
        int &p = a[i].p = lca(x, y), &xx = a[i].xx = gson(x, p), &yy = a[i].yy = gson(y, p);
        ++mp[pii(xx, yy)], ++mp[pii(yy, xx)];
        ++f1[p], ++f2[x], ++f2[y], --f2[p], ++gg[xx], ++gg[yy];
    }
    dfs3(1), dfs4(1);
    ll ans = 0;
    for (int i = 1; i <= m; ++i) {
        const int &x = a[i].x, &y = a[i].y, &p = a[i].p;
        int cnt = f2[p], xx = a[i].xx, yy = a[i].yy;
        if (xx) {
            cnt -= dis[x] - dis[xx];
            cnt -= f1[x];
        }
        if (yy) {
            cnt -= dis[y] - dis[yy];
            cnt -= f1[y];
        }
        if (xx && yy) cnt -= f1[p] - f1[xx] - f1[yy] - gg[xx] - gg[yy] + mp[pii(xx, yy)] + (ss[p] - ss[xx] - ss[yy] + gg[xx] + gg[yy]);
        else if (xx) cnt -= f1[p] - f1[xx] - gg[xx] + (ss[p] - ss[xx] + gg[xx]);
        else if (yy) cnt -= f1[p] - f1[yy] - gg[yy] + (ss[p] - ss[yy] + gg[yy]);
        ans += cnt - 1;
    }
    printf("%lld\n", ans / 2);
}

inline void init() {
    read(n), read(m), m -= n - 1;
    int x, y;
    for (int i = 1; i < n; ++i) read(x), read(y), adde(x, y);
    for (int i = 1; i <= m; ++i) read(a[i].x), read(a[i].y);
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#else
    File(exercise);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

tracking2

トピックポータル

http://192.168.21.187/contest/30/problem/3

http://47.100.137.146/contest/30/problem/3

問題の解決策

明らかに、隣接する二つのための\(C_1、C_2 \) および\(C_1 \ NEQ C_2 \) もし\(C_1 <C_2 \) そう\(A_1 = C_1 \) そうでなければ\(A_2 = C_2 \) 。

我々は、元の多く置くことができる\(\)間隔の数は、多くのセクションに分割されて修正されたシーケンス番号を、フォームの各セクションは、任意の必要とされる(K \)\を隣接の最小数\(Y-の\) 次いで毎に存在する\(X = 10 ^ 9 - Y + 1 \) 値の種類。

この要件は、DPで完了したと見なされます。だから、\(DP [i]が\)最初のために\(私は\)位置を答えます。

最初の転送がある\( - CDOT X \ \ [1。I] DP [I] DP =)

しかしながら、可能な問題がある(.. I-K + 1 \ iは\) この期間は、全てよりも大きくすることができる\(X \) 満たしていない(\ \分= x)から\を

だから我々はタイトルの意味を満たしていない部分を失うする必要があり、\(I-K + 1 ..私は、\)この段落は、すべてのよりも大きくすることができる\(X- \)プログラムがあり、\((X-1)^ kの\をその後、以降\(DP [iが- 1] \) がなければならないので、合法である\(X \)続いて\(K-1 \)よりも大きい第\(X \)ケース番号。したがって、部分を減算することによって乗算される\(DP [IK-1]の\ CDOT(X-1)^ k個の\) 。

だから、解決策は、段落にある\(DP [N-] \)、\ (N- \)この期間の長さ。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

const int N = 1e5 + 7;
const int P = 1e9 + 7;

int n, k, m;
int c[N], dp[N];

inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
inline int fpow(int x, int y) {
    int ans = 1;
    for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
    return ans;
}

inline int DP(const int &n, const int &x) {
    if (n <= 0) return 1;
    dp[0] = 1;
    int thx = fpow(x - 1, k);
    for (int i = 1; i <= n; ++i) {
        dp[i] = (ll)dp[i - 1] * x % P;
        if (i >= k + 1) sadd(dp[i], P - (ll)dp[i - k - 1] * thx % P);
        else if (i >= k) sadd(dp[i], P - thx);
    }
    return dp[n];
}

inline void work() {
    int ans = 1;
    for (int i = 1; i <= m; ++i) {
        int l = i, r = i, st;
        while (r < n && c[r + 1] == c[l]) ++r;
        st = r - l + k;
        if (r < m && c[r + 1] > c[r]) st -= k;
        if (l > 1 && c[l - 1] > c[l]) st -= k;
        ans = (ll)ans * DP(st, 1e9 - c[l] + 1) % P;
        i = r;
    }
    printf("%d\n", ans);
}

inline void init() {
    read(n), read(k), m = n - k + 1;
    for (int i = 1; i <= m; ++i) read(c[i]);
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#else
    File(tracking2);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

おすすめ

転載: www.cnblogs.com/hankeke/p/contest20190922.html