"2019 Jizhong training Day7" problem-solving report

T1, a small number of columns L

Give a series \ (\ {F_i \} \) : \
[F_i = \ prod_ {J =. 1} ^ {J \ Leq K} F_ {I - J} ^ {b_j}, \ (I> K) \]
now given number of columns before the \ (k \ (k \ le 200) \) term and \ (B_i} {\) , seeking the first \ (n-\) key.

\ (Sol \) :
took note of an arbitrary number of columns \ (F_i \ (I> K) \) , the former are \ (K \) product terms of a power of just the first one, respectively, calculated for each \ (n \) contribution items.
Note \ (dp_i \) represents the \ (I \) exponent, is difficult to draw:
\ [dp_i = \ J = I sum_ {-} ^ K {J \ I Leq - B_. 1} I {-} J \ times dp_j \]

Obviously matrix multiplication can be used to optimize, because the former are enumerated \ (K \) item, time complexity \ (O (K ^. 4 \ \ n-log_2) \) .
Each transition matrix is the same, it is possible to \ (O (k ^ 3 \ \ log_2 n) \) of time to resolve complex.

code show as below:

#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int M = 205, mod = 998244353;
int n, m, f[205], y[205], a[205], b[205], res;

struct matrix {
    int a[M][M];
    matrix(int t = 0) {
        memset(a, 0, sizeof(a));
        if (t > 0)
            for (int i = 1; i <= m; ++i)
                a[i][i] = t;
    }
    inline int* operator [] (int x) {
        return a[x];
    }
    inline matrix operator * (matrix &b) const {
        matrix ret;
        for (int k = 1; k <= m; ++k)
            for (int i = 1; i <= m; ++i)
                if (a[i][k])
                    for (int j = 1; j <= m; ++j)
                        if (b[k][j]) {
                            ret[i][j] += 1ll * a[i][k] * b[k][j] % (mod - 1);
                            if (ret[i][j] >= mod - 1)
                                ret[i][j] -= mod - 1;
                        }
        return ret;
    }
} ;

matrix matrix_qpow(matrix base, int b) {
    matrix ret(1);
    for (; b; b >>= 1, base = base * base)
        if (b & 1)
            ret = ret * base;
    return ret;
}
int qpow(int base, int b, int ret = 1) {
    for (; b; b >>= 1, base = 1ll * base * base % mod)
        if (b & 1)
            ret = 1ll * ret * base % mod;
    return ret;
}

int main() {
    //freopen("in", "r", stdin);
    freopen("seq.in", "r", stdin);
    freopen("seq.out", "w", stdout);
    matrix trans;
    n = in(), m = in();
    for (int i = 1; i <= m; ++i)
        y[i] = in();
    for (int i = 1; i <= m; ++i)
        f[i] = in();

    if (n <= m) {
        printf("%d\n", f[n]);
        return 0;
    }

    for (int i = 1; i <= m; ++i)
        trans[i][i - 1] = 1;
    for (int i = 1; i <= m; ++i)
        trans[i][m] = y[m - i + 1];

    res = 1;
    trans = matrix_qpow(trans, n - m);
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= m; ++j)
            b[j] = a[j] = 0;
        b[i] = 1;
        for (int k = 1; k <= m; ++k)
            for (int j = 1; j <= m; ++j) {
                a[j] += 1ll * b[k] * trans[k][j] % (mod - 1);
                if (a[j] >= mod - 1)
                    a[j] -= mod - 1;
            }
        res = 1ll * res * qpow(f[i], a[m]) % mod;
    }

    printf("%d\n", res);

    return 0;
}

T2, dreams

Given the number line \ (n-\) line segments \ (\ {L_i, r_i \} \) , \ (m \) points \ (\ {t_i \} \) , each match line segment is not selected and included in a a point of the line segment match, find the maximum number of matches.

\ (70pts \) :
segment tree diagram seek to optimize the construction bipartite graph maximum matching.

\ (100 pts \) : \
(Sol 1 \) :
Point from small to large, the left end line segment from small to large;
from small to large to enumerate all the points, put the left point to the left of the point of the segment into the stack (right end point small root heap) the keywords;
whether the right spot checks top of the heap in the current enumeration to point to the right, and if so, will change to match point and the top of the heap segment; otherwise, repeat the process until the condition is satisfied or heap is air.
For the first \ (i \) points will be affected only in its right point, in order to make the point to the right of the line can have more choices, so choose the right leftmost point.
\ (Sol 2 \) :
line press the right endpoints from small to large, point into the Fenwick tree;
enumerate each segment, each segment have chosen to keep the left point.
And \ (Sol1 \) the same.

code show as below:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 2e5 + 5;
struct node {
    int l, r;
    inline bool operator < (const node &b) const {
        return this->r > b.r;
    }
} a[N];
int n, m, t[N];

inline bool cmp(const node &i, const node &j) {
    return i.l < j.l;
}

int main() {
    //freopen("in", "r", stdin);
    freopen("dream.in", "r", stdin);
    freopen("dream.out", "w", stdout);
    n = in(), m = in();
    for (int i = 1; i <= n; ++i)
        a[i] = (node){in(), in()};
    for (int i = 1; i <= m; ++i)
        t[i] = in();
    std::sort(a + 1, a + 1 + n, cmp);
    std::sort(t + 1, t + 1 + m);
    std::priority_queue <node> q;
    int pos = 1, res = 0;
    for (int i = 1; i <= m; ++i) {
        while (pos <= n && a[pos].l <= t[i]) {
            if (a[pos].r >= t[i])
                q.push(a[pos]);
            ++pos;
        }
        while (!q.empty() && q.top().r < t[i])
            q.pop();
        if (!q.empty() && q.top().r >= t[i])
            ++res, q.pop();
    }
    printf("%d\n", res);
    return 0;
}

T3, tree

A \ (n-\) points of the tree, a given \ (m \ (m \ leq 10 ^ 5) \) points to (guaranteed two different points), not including the point of demand and the number of points greater than one simple path.

\ (Sol \) :
Consider seeking at least the number of paths contains a set of pairs of points.
The end of a path on a two-dimensional plane, a point can represent a path;
for a point \ (U, v \) :
If there are two things ancestor - descendant relationship ( \ (U \) to \ (v \) ancestors), the two end points of the range of available paths are \ (V \) in the sub-tree, in addition to \ (U \) comprising \ (V \) all other points of the subtree.
If no ancestor two - descendant relationship, the two end points of the range of available paths are \ (U \) subtree, \ (V \) subtrees.
Press \ (DFS \) sequence on a plane, a scanning line into a rectangular footprint questions seeking area, segment tree to maintain.
Maintenance segment tree: you can \ (push_down \) can not, the former more scalable, due to the deletion of certain segments of scan lines to join, so I do not use \ (push_down \) .

code show as below:

//#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 1e5 + 5;

struct edge {
    int next, to;
} e[N << 1];
int ecnt = 1, head[N];

inline void jb(const int u, const int v) {
    e[++ecnt] = (edge){head[u], v}, head[u] = ecnt;
    e[++ecnt] = (edge){head[v], u}, head[v] = ecnt;
}

//heavy-light deposition begin
int siz[N], hson[N], fa[N], dep[N], fro[N], dfn[N];
void dfs_h(const int u) {
    siz[u] = 1;
    for (int i = head[u]; i; i = e[i].next) {
        int v = e[i].to;
        if (v == fa[u])
            continue;
        fa[v] = u, dep[v] = dep[u] + 1;
        dfs_h(v);
        siz[u] += siz[v];
        if (siz[v] > siz[hson[u]])
            hson[u] = v;
    }
}

void dfs_f(const int u, const int tp) {
    dfn[u] = ++dfn[0], fro[u] = tp;
    if (hson[u])
        dfs_f(hson[u], tp);
    for (int i = head[u]; i; i = e[i].next)
        if (e[i].to != fa[u] && e[i].to != hson[u])
            dfs_f(e[i].to, e[i].to);
}
int lca(int u, int v) {
    while (fro[u] != fro[v]) {
        if (dep[fro[u]] > dep[fro[v]])
            std::swap(u, v);
        v = fa[fro[v]];
    }
    return dep[u] < dep[v] ? u : v;
}
int find_son(int u, int v) {
    while (fro[v] != fro[u]) {
        v = fro[v];
        if (fa[v] == u)
            return v;
        v = fa[v];
    }
    return hson[u];
}
//heavy-light deposition end

int n, m;

typedef std::pair<int, int> pii;
std::vector<pii> a[N][2];

struct segment_tree {
    int sum[N << 2], cnt[N << 2];
    void push_up(int p, int tl, int tr) {
        if (cnt[p])
            sum[p] = tr - tl + 1;
        else if (tl == tr)
            sum[p] = 0;
        else
            sum[p] = sum[p << 1] + sum[p << 1 | 1];
    }
    void modify(int l, int r, int k, int tl = 1, int tr = n, int p = 1) {
        if (l <= tl && tr <= r) {
            cnt[p] += k;
            push_up(p, tl, tr);
            return ;
        }
        int mid = (tl + tr) >> 1;
        if (mid >= l)
            modify(l, r, k, tl, mid, p << 1);
        if (mid < r)
            modify(l, r, k, mid + 1, tr, p << 1 | 1);
        push_up(p, tl, tr);
    }
} T;

int main() {
    //freopen("in", "r", stdin);
    freopen("tree.in", "r", stdin);
    freopen("tree.out", "w", stdout);
    n = in(), m = in();
    for (int i = 1; i < n; ++i)
        jb(in(), in());
    dfs_h(3), dfs_f(3, 3);
    for (int i = 1, u, v, w; i <= m; ++i) {
        u = in(), v = in(), w = lca(u, v);
        if (dfn[u] > dfn[v])
            std::swap(u, v);
        if (w == u) {
            w = find_son(u, v);
            a[1][0].push_back(pii(dfn[v], dfn[v] + siz[v] - 1));
            a[dfn[w]][1].push_back(pii(dfn[v], dfn[v] + siz[v] - 1));
            a[dfn[v]][0].push_back(pii(dfn[w] + siz[w], n));
            a[dfn[v] + siz[v]][1].push_back(pii(dfn[w] + siz[w], n));
        } else {
            a[dfn[u]][0].push_back(pii(dfn[v], dfn[v] + siz[v] - 1));
            a[dfn[u] + siz[u]][1].push_back(pii(dfn[v], dfn[v] + siz[v] - 1));
        }
    }

    long long res = 1ll * n * (n - 1) / 2;
    for (int i = 1; i < n; ++i) {
        for (unsigned j = 0; j < a[i][0].size(); ++j)
            T.modify(a[i][0][j].first, a[i][0][j].second, 1);
        for (unsigned j = 0; j < a[i][1].size(); ++j)
            T.modify(a[i][1][j].first, a[i][1][j].second, -1);
        res -= T.sum[1];
    }
    printf("%lld\n", res);
    return 0;
}

Guess you like

Origin www.cnblogs.com/15owzLy1-yiylcy/p/11321993.html