Codeforces 1214 FGH補数タイトルレコード

#583を再生する前にオープンした、フィールドは後に5つの質問を平準化されていません。最近、私はSBデバッグプロセスを記録するために、問題について補うために。

私は長い時間のためにタイトル曲の前にはすでにZZので、私はこのレベルは、あまりにも生きることはできないと思います......


F:あなたのリング、いくつかのポイントを与えることである、距離に必要な最小のオフペア。

明らかにマッチングエッジああと交差しません。それは直接だけで罰金リングへ。

死角の変化の方向を推測するための貢献が特に大きくない、貢献度を計算し検討します、問題の解決策を確認するために見ます見つかっ推測として状況を証明します。

明らかに、考慮(X \ YのLeq \)\、次いで固定\(Y \) その結果、カットオフポイントが存在しなければならない( - X> M - X + Y \ Y)\

長開く(N- \)\アレイターンを示し、\(\ FRAC {2 \ {N-PI Iを}} \)

したがって、各ポイントのライン上の同じ貢献、直接および差動プレフィックスの継続期間のため、貢献度を計算します。

境界はまだ、すなわち、慎重に考慮されなければならない\(Y - X = M - X + Yの\) 時間。その後、我々は時間の関数として書かれた国境に注意を払う必要があり、二重性と、それぞれ二つのリングの貢献を考えてみましょう。

多くはないの詳細は、Aの後にそれをサンプリング。

#include <bits/stdc++.h>
 
const int MAXN = 200010;
typedef long long LL;
int n, R;
struct node {
    LL at; int id;
    bool operator < (node b) const { return at < b.at; }
} as[MAXN], bs[MAXN];
int ansl[MAXN];
LL pre1[MAXN], pre2[MAXN], * pre;
void _mkadd(int l, int r, int v) {
    pre[l] += v, pre[r + 1] -= v;
}
void mkadd(int l, int r, int v, int dta) {
    if (l >= r) return ;
    --r;
    l = (l - 1 - dta + n) % n + 1;
    r = (r - 1 - dta + n) % n + 1;
    if (l <= r) _mkadd(l, r, v);
    else _mkadd(1, r, v), _mkadd(l, n, v);
}
void pusharr(int at, node * dst, int dta) {
    node * it;
    if (dst == bs)
        it = std::lower_bound(dst + 1, dst + 1 + n, (node) {at << 1, 0});
    else
        it = std::upper_bound(dst + 1, dst + 1 + n, (node) {at << 1, 0});
    node * lhs = std::upper_bound(dst + 1, it, (node) {2 * at - R, 0});
    node * rhs = std::lower_bound(it, dst + 1 + n, (node) {2ll * at + R, 0});
    const int delta = (dst != as) * R;
    mkadd(1, lhs - dst, delta - at, dta);
    mkadd(lhs - dst, it - dst, at, dta);
    mkadd(it - dst, rhs - dst, -at, dta);
    mkadd(rhs - dst, 1 + n, delta + at, dta);
}
int main() {
    std::ios_base::sync_with_stdio(false), std::cin.tie(0);
    std::cin >> R >> n;
    for (int i = 1; i <= n; ++i) as[i].id = i, std::cin >> as[i].at;
    for (int i = 1; i <= n; ++i) bs[i].id = i, std::cin >> bs[i].at;
    std::sort(as + 1, as + 1 + n);
    std::sort(bs + 1, bs + 1 + n);
    for (int i = 1; i <= n; ++i) as[i].at <<= 1, bs[i].at <<= 1;
    for (int i = 1; i <= n; ++i) {
        pre = pre1, pusharr(as[i].at >> 1, bs, i - 1);
        pre = pre2, pusharr(bs[i].at >> 1, as, i - 1);
    }
    LL ans = 0x3f3f3f3f3f3f3f3fLL; int at = 1;
    for (int i = 1; i <= n; ++i)
        pre1[i] += pre1[i - 1], pre2[i] += pre2[i - 1];
    for (int i = 1; i <= n; ++i) {
        LL now = pre1[i] + pre2[i > 1 ? n - i + 2 : 1];
        if (now < ans) ans = now, at = i;
    }
    for (int i = 1; i <= n; ++i)
        ansl[as[i].id] = bs[(i + at - 2) % n + 1].id;
    std::cout << ans << std::endl;
    for (int i = 1; i <= n; ++i)
        std::cout << ansl[i] << ' ';
    std::cout << std::endl;
    return 0;
}

G:長方形の4つの頂点について問い合わせ、対角が等しい点の反対側の隣接辺、変形のラインセクション。

データ範囲、参照してください\(タイムズ\メートルを9 Q = 10 ^ \) 自然なビットセット。しかし、どのようにそれを維持するには?

2つの行を考える、示さ\(A \)する一行\(1 \)それらが現れる、\(B \)別の行である\(1 \)は、(完全な)全ての位置である、(U- \)\

その\(\キャップ\左( U \バックスラッシュBの\右)\) と\(B \キャップ\左( U \バックスラッシュA \右)\) 非空である、と呼ばれる判別関数\(F( 、B)= [A \ CAP \左(U- \バックスラッシュBの\右)\ NEQ \ emptySet] [B \キャップ\左(U- \バックスラッシュ\右)\ NEQ \ emptySet] \)

問題の解決策によると、、\ (\ NEG F \は(A、B \右)\左)推移を。実際には、このコレクションは二組が相互に排他的であれば問題は、解決可能になりますされて含まれています。(私も料理は、上記の包含関係から期待していませんでした)

その後、明らかにそれは、鎖ない溶液の形成との間の関係を含みます。コレクションのサイズがソートされたことにより、私たちは直接、その後のメンテナンスは、関係のコレクションを格納するのに隣接していません。

手書きのこつを書くBITSET ......一見、高効率をSTLませんでした。

#include <bits/stdc++.h>
 
const int MAXN = 2000;
typedef long long LL;
int n, m, Q;
const int dig = 2048 / 64;
struct bitset {
    LL A[dig]; int ppc;
    bool contains(const bitset & b) const {
        for (int i = 0; i != dig; ++i)
            if ((A[i] & b.A[i]) != b.A[i])
                return false;
        return true;
    }
    void rev(int l, int r) {
        for (int i = (l >> 6); i <= (r >> 6); ++i)
            ppc -= __builtin_popcountll(A[i]);
        A[l >> 6] ^= ((1ll << (l & 63)) - 1) ^ -1;
        A[r >> 6] ^= (r & 63) == 63 ? -1 : (1ll << ((r & 63) + 1)) - 1;
        (l >> 6) == (r >> 6) ? (A[l >> 6] ^= -1) : 0;
        for (int i = (l >> 6) + 1; i < (r >> 6); ++i) A[i] ^= -1;
        for (int i = (l >> 6); i <= (r >> 6); ++i)
            ppc += __builtin_popcountll(A[i]);
    }
    int ctzofandinvb(const bitset & b) {
        for (int i = 0; i != dig; ++i) {
            LL now = A[i] & ~b.A[i];
            if (now) return i << 6 | __builtin_ctzll(now);
        }
        return -1;
    }
} mat[MAXN];
typedef std::pair<int, int> PII;
std::set<PII> S, diff;
int getsuc(std::set<PII>::iterator it) {
    return ++it != S.end() ? it -> second : -1;
}
int getpre(std::set<PII>::iterator it) {
    return it != S.begin() ? (--it) -> second : -1;
}
void ins(int a, int b) {
    if (a == -1 || b == -1) return ;
    if (!mat[b].contains(mat[a]))
        diff.insert(PII(a, b));
}
void del(int a, int b) {
    if (a == -1 || b == -1) return ;
    diff.erase(PII(a, b));
}
bitset t;
int main() {
    std::ios_base::sync_with_stdio(false), std::cin.tie(0);
    std::cin >> n >> m >> Q;
    for (int i = 0; i < n; ++i) S.insert(PII(0, i));
    int t1, t2, t3;
    while (Q --> 0) {
        std::cin >> t1 >> t2 >> t3; --t1, --t2, --t3;
        auto t = S.find(PII(mat[t1].ppc, t1));
        int suc = getsuc(t), pre = getpre(t);
        del(pre, t1); del(t1, suc);
        S.erase(t); mat[t1].rev(t2, t3);
        auto at = S.insert(PII(mat[t1].ppc, t1)).first;
        int ts = getsuc(at), tp = getpre(at); 
        del(tp, ts);
        ins(tp, t1); ins(t1, ts);
        if (ts != suc && tp != pre) ins(pre, suc);
        if (diff.empty()) std::cout << "-1\n";
        else {
            PII t = *diff.begin();
            int x1 = t.first, x2 = t.second;
            int y1 = mat[x1].ctzofandinvb(mat[x2]);
            int y2 = mat[x2].ctzofandinvb(mat[x1]);
            if (x1 > x2) std::swap(x1, x2);
            if (y1 > y2) std::swap(y1, y2);
            ++x1, ++x2, ++y1, ++y2;
            std::cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\n';
        }
    }
    return 0;
}

H:ツリー\(K \)染色、すべての長さとなるよう\(K \)パスが全て含まれていることを起こる\(K \)色。

簡単な質問が、私は場所SBの束を掛け

もちろん、あなたは直径を見つける必要があります。次いで直径位置調整色に応じて、直径がサブツリーを挿入します。下から割り当てられた順番の色。

これにより、我々はケースに解決策を考えてみません:

直径で、左右からダウンすることができた場合、直径は回文でなければなりません。

したがって、最初の文は、アウト特別\(K = 2 \)場合は、残りの直径は確かにパリンドロームではありません。

一見すると、この判断は弱すぎます。我々は2つのサブ木が綴ることができ、色分布、ダウン2のサブツリーに分岐流通チェーンの祖先、チェーンの長さの考慮\(K \)チェーンのを、このチェーンは回文、確かにありませんソリューションを存在しなければならないということ。

すなわち点があり、三の方向に\(A、B、C \)、\ (AB、BC、AC \)三の方向超える鎖長に等しい\(K \)

だから、最後の質問は、直径に行くする方法を検討することです。

割り当てられた右側からダウン場合、数\(デルタ= -1 \) そうでなければ\(1 \)

私がプラス求めて直径を完了しなかったと言われて\(1 \)小さな点につながり、DPはサブツリー無用の根本原因で接合されたときに\(ノー\)ハングアップしたように言い渡され、書くべき2つのモジュロあります\(K \を)結果書かれた\(R \) ......

実際には多くの詳細。

#include <bits/stdc++.h>
 
const int MAXN = 200010;
void bye() { std::cout << "No\n"; exit(0); }
int head[MAXN], nxt[MAXN << 1], to[MAXN << 1], tot;
void addedge(int b, int e) {
    nxt[++tot] = head[b]; to[head[b] = tot] = e;
    nxt[++tot] = head[e]; to[head[e] = tot] = b;
}
int ansl[MAXN];
int n, K;
void simpledfs(int u, int fa = 0, int col = 1) {
    ansl[u] = col;
    for (int i = head[u]; i; i = nxt[i])
        if (to[i] != fa)
            simpledfs(to[i], u, col ^ 1);
}
int dis[MAXN];
void dfsx(int u, int fa = 0) {
    for (int i = head[u]; i; i = nxt[i])
        if (to[i] != fa) {
            dis[to[i]] = dis[u] + 1;
            dfsx(to[i], u);
        }
}
const int INF = 0x3f3f3f3f;
struct data {
    int a[3];
    data() { a[0] = a[1] = a[2] = -INF; }
    void insert(int x) {
        if (x >= a[0]) a[2] = a[1], a[1] = a[0], a[0] = x;
        else if (x >= a[1]) a[2] = a[1], a[1] = x;
        else if (x >= a[2]) a[2] = x;
    }
    void shift() { ++a[0], ++a[1], ++a[2]; }
} val[MAXN], vt[MAXN];
void dfs1(int u, int fa = 0) {
    for (int i = head[u]; i; i = nxt[i])
        if (to[i] != fa) {
            dfs1(to[i], u);
            val[u].insert(std::max(val[to[i]].a[0], 0) + 1);
        }
}
void dfs2(int u, int fa = 0, int upv = 0) {
    for (int i = head[u]; i; i = nxt[i])
        if (to[i] != fa) {
            int tv = std::max(upv, val[u].a[val[to[i]].a[0] + 1 == val[u].a[0]]) + 1;
            dfs2(to[i], u, tv);
        }
    vt[u] = val[u]; if (fa) vt[u].insert(upv);
    if (vt[u].a[2] + vt[u].a[1] + 1 >= K) bye();
}
int li[MAXN], inc[MAXN];
bool mark(int u, int dst, int fa = 0) {
    if (u == dst) {
        li[dis[u]] = u;
        return true;
    }
    for (int i = head[u]; i; i = nxt[i])
        if (to[i] != fa) {
            if (mark(to[i], dst, u)) {
                li[dis[u]] = u;
                return true;
            }
        }
    return false;
}
int R;
void dfsmk(int u, int fa, int now, int delta) {
    now = (now + delta) % K;
    ansl[u] = now;
    for (int i = head[u]; i; i = nxt[i])
        if (to[i] != fa)
            dfsmk(to[i], u, now, delta);
}
int main() {
    std::ios_base::sync_with_stdio(false), std::cin.tie(0);
    std::cin >> n >> K;
    for (int i = 1, t1, t2; i < n; ++i) {
        std::cin >> t1 >> t2;
        addedge(t1, t2);
    }
    if (K == 2) simpledfs(1);
    else {
        dfs1(1); dfs2(1);
        dis[1] = 0; dfsx(1);
        int at = 1, rt;
        for (int i = 2; i <= n; ++i) if (dis[i] > dis[at]) at = i;
        dis[at] = 0; dfsx(rt = at);
        at = 1;
        for (int i = 2; i <= n; ++i) if (dis[i] > dis[at]) at = i;
        R = dis[at] + 1;
        mark(rt, at);
        for (int i = 0; i < R; ++i) inc[li[i]] = true;
        for (int i = 0; i < R; ++i) {
            ansl[li[i]] = i % K;
            int dta = R - 1 - i > i ? K - 1 : 1;
            for (int j = head[li[i]]; j; j = nxt[j])
                if (!inc[to[j]])
                    dfsmk(to[j], li[i], i, dta);
        }
    }
    std::cout << "Yes" << std::endl;
    for (int i = 1; i <= n; ++i) std::cout << ansl[i] + 1 << ' ';
    std::cout << std::endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/daklqw/p/11692692.html