AGC006は、小さなノートに疑問を行います

ゲームリンク:AGC006

C.Rabbitエクササイズ

問題の意味

n個のウサギに、ウサギは、I X [i]の開始に位置しています。操作、I A所与操作がmはIを 1又は[I] + 1ウサギ、それをスキップに対して-それは[I]等ウサギ[I]を選択する確率を表すので、ウサギの対称ポイント。

操作後のm k回の出力を繰り返すようにあなたを掲載し、各ウサギの座標は、望ましいです。

3≤N、M≤100000

1018≤1≤K

問題の解決策

800ポイントで1500 points以上に困難シリーズ

1つのジャンプを行うには、Y対称のxは2Yをジャンプします - X

だから、ウサギのウサギのジャンプ、B、bは彼の貢献の場所にジャンプする際に直線的です。+ 0.5 *(2 * X [T + 1の所望の線形結合、我々はジャンプがX [T] 0.5 *(X [T] 2 * X - [ - 1 T])となることがある作るTを描くことができ] - X [T])= xで[T - 1] + X [T + 1] - X [T]

これは、取り扱いが困難と思われます。次に、以下の図を描く場合は、差動変化の配列は、xが非常に興味深いジャンプができます。

令D1 = X [T] - X [T - 1]、D2 = xで[T + 1] - X [T]

Tに - 1ジャンプの結果であり、D1 = -d1、D2 = 2×D1 + D2

T + 1にジャンプ結果である、D2 = -d2、D1 = D1 + 2 * D2

次に、目的の直線性、我々はトンジャンプはD1およびD2に交換させて一度見つけます

したがって、mはアレイの差動変位に作用する操作と等価です

Mアナログフロント操作は順列を決定することができます。回転交換の数に分割すると、あなたは、k番目の力でそれを見つけることができます。

x1は、最終的なシーケンスを復元することができ、差分配列を取得するために変更されません。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5 + 10;
 
int n, m, a[N], p[N], vis[N];
vector<int> vec;
LL x[N], k, d[N], res[N];
 
void dfs(int x) {
    vis[x] = 1;
    vec.push_back(x);
    if (!vis[p[x]]) dfs(p[x]);
}
 
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld", &x[i]);
    }
    for (int i = 1; i < n; ++i)
        d[i] = x[i + 1] - x[i];
    scanf("%d%lld", &m, &k);
    for (int i = 1; i < n; ++i)
        p[i] = i;
    for (int i = 1; i <= m; ++i) {
        scanf("%d", &a[i]);
        swap(p[a[i] - 1], p[a[i]]);
    }
    for (int i = 1; i < n; ++i) {
        if (vis[i]) continue;
        vec.clear();
        dfs(i);
        int siz = vec.size();
        int del = k % siz;
        for (int j = 0; j < vec.size(); ++j) 
            res[vec[j]] = d[vec[(j + del) % siz]];
    }
    LL ans = x[1];
    printf("%lld\n", ans);
    for (int i = 1; i < n; ++i) {
        ans += res[i];
        printf("%lld\n", ans);
    }
    return 0;
}

D.Medianピラミッドハード

問題の意味

2n個の所定の長さ - ピラミッドの第一の層として1内に配置した後、我々はn層、i番目のレイヤ2 *(N - I)のピラミッド構築+ 1数。第2層の開始から、第一の層は、xの数X、X + 1、X + 2中央値に等しく、トップの数がどのくらいに尋ねました。

N≤100000

問題の解決策

1500ポイントよりも困難な1300ディビジョンシリーズ

明らかに二分答えがあり、その後、オリジナルシリーズは、01列になります。

底層01インターリーブ場合、トップ数は最初の数に等しい、時間を確認し、そうでない場合、両者が同じ0連続し、それは、2つの0の「柱」の上に形成することになるが考えている場合、この列aを出会い後の国境に、左または右上を起動します。あなたが複数の列を持っている場合、それは勝つ特定の長距離アップで見つけることができます。だから、最も近いを見つける必要があるのnフラナガンの柱とすることができます。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5 + 10;
 
int n, m, a[N * 2], b[N * 2];
 
int check(int mid) {
    int dis = 0x3f3f3f3f;
    for (int i = 1; i <= n * 2 - 1; ++i)
        b[i] = (a[i] >= mid);
    int ans = b[1];
    for (int i = 1; i < n * 2 - 1; ++i) {
        if (b[i] == b[i + 1]) {
            int d = min(abs(n - i), abs(n - i - 1));
            if (d < dis) {
                dis = d;
                ans = b[i];
            }
        }
    }
    return ans;
}
 
int main() {
    cin >> n;
    for (int i = 1; i <= n * 2 - 1; ++i)
        scanf("%d", &a[i]);
    int l = 1, r = 2 * n - 1;
    while (l < r) {
        int mid = (l + r + 1) >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    cout << l << endl;
    return 0;
}

E.Rotateの3x3の

問題の意味

3 - 長方形の3行n列が与えられると、第i行j列の番号i + 3Jです。矩形は180°回転するたびに、3×3を選択し、矩形が所定の目標状態に動作させることができるかどうかを尋ねられることができます。

問題の解決策

ハンドプレイ大法が良いです!

まず、あなたは長方形を回転させるのに役立つプログラムを記述する必要があります。手は10分を果たし、あなたはいくつかの非常に有用な性質を見つけます。

まず、列間の列数を交換することができず、残りの32の弾性率は、中央に常にあります。

(第一行及び第三行のスイッチング素子)しながら、これらの列を反転させることができるように第二に、距離があっても2である場合

2人の距離が2である場合、最終的に、2つの列を交換することができ、中央の列は否定します

パリティの最終的な、奇数列偶数列パリティに等しい列の逆数を逆に列のi番目の列の値が偶数列その逆、実現可能であることに注意してください。

この意志WA3ポイント、だけでなく、何の文Cirièのオリジナルの長方形はどこへ行くにもコラムを行ってきましたがありませんので。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;

int n, a[3][N];
int p[N], v[N], to[N];
int b[N], tr[N * 3];

void Add(int x) {
    while (x <= n * 3) {
        tr[x] ^= 1;
        x += x & -x;
    }
}

int Query(int x) {
    int ans = 0;
    while (x) {
        ans ^= tr[x];
        x -= x & -x;
    }
    return ans;
}

int inv(int *a, int n) {
    memset(tr, 0, sizeof tr);
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        ans ^= Query(n * 3) ^ Query(a[i]);
        Add(a[i]);
    }
    return ans;
}

int main() {
    cin >> n;
    for (int i = 0; i < 3; ++i) {
        for (int j = 1; j <= n; ++j)
            scanf("%d", &a[i][j]);
    }
    for (int i = 1; i <= n; ++i) {
        if (a[0][i] % 3 == 1) {
            if (a[1][i] != a[0][i] + 1) return 0 * puts("No");
            if (a[2][i] != a[1][i] + 1) return 0 * puts("No");
            p[i] = (a[0][i] - 1) / 3 + 1;
            v[i] = 0;
        }
        if (a[0][i] % 3 == 0) {
            if (a[1][i] != a[0][i] - 1) return 0 * puts("No");
            if (a[2][i] != a[1][i] - 1) return 0 * puts("No");
            p[i] = a[0][i] / 3;
            v[i] = 1;
        }
        if (a[0][i] % 3 == 2) return 0 * puts("No");
    }
    for (int i = 1; i <= n; ++i)
        to[p[i]] = i;
    for (int i = 1; i <= n; ++i) {
        if ((i + to[i]) & 1) return 0 * puts("No");
    }
    
    int m = (n + 1) / 2;
    for (int i = 1; i <= m; ++i)
        b[i] = p[i * 2 - 1];
    int tmp = inv(b, m);
    for (int i = 1; i <= n; ++i)
        if (i % 2 == 0)
            tmp ^= v[i];
    if (tmp) return 0 * puts("No");

    m = n / 2;
    for (int i = 1; i <= m; ++i)
        b[i] = p[i * 2];
    tmp = inv(b, m);
    for (int i = 1; i <= n; ++i)
        if (i & 1)
            tmp ^= v[i];
    if (tmp) return 0 * puts("No");
    return 0 * puts("Yes");
}

F.Blackout

問題の意味

YとYエッジ、エッジZとX、次にX上部Zに接続することができれば、有向グラフを与え

Mは、ボーダー図できるだけエッジの必要数後に、最初だけエッジ。

問題の解決策

1700点以上1500点難しいシリーズ(霧)

この質問は非常に賢いです。

まず、我々は別に弱いリンクブロックを計算することができます。

弱いユニコムブロックはユニコム図なし裏側に全ての辺を交換することです。

そして、私たち3人ユニコムブロックを染色しました。

汚れがトリコロールを必要としない場合は、明らかにプラス側にすることはできません。

あなたは3つのコレクションのサイズに分け、三色の染色セットすることが起こるならば、同じことが弱点であるため、Aは、Bは、Cは、その後、答えの寄与はこれは*のB + B *のC + C * Aであるであり、ユニコムのブロック間の無限大、必ずしも互いに接続された2つの縁部の2つの異なるセット、第3の辺が存在しなければならないようにします。

三色染色ができない場合は、同じセット内のエッジが存在すること、次いで、付加側の完了後に完全グラフでなければなりません。証拠と旧。

ユニコムは弱い文言を調べる必要があります。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2e5 + 10;

int n, m, E, cnt;
int fir[N], nex[N], arr[N], val[N], vis[N];
LL A, B, C, flag, col[N];

inline void Add_Edge(int x, int y, int w) {
    nex[++E] = fir[x];
    fir[x] = E; arr[E] = y; val[E] = w;
}

void dfs(int x) {
    vis[x] = 1;
    if (col[x] == 0) ++A;
    if (col[x] == 1) ++B;
    if (col[x] == 2) ++C;
    for (int i = fir[x]; i; i = nex[i]) {
        if (val[i] == 1) ++cnt;
        if (vis[arr[i]]) {
            if (col[arr[i]] != (col[x] + val[i]) % 3)
                flag = 1;
        }
        else {
            col[arr[i]] = (col[x] + val[i]) % 3;
            dfs(arr[i]);
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int x, y;
        scanf("%d%d", &x, &y);
        Add_Edge(x, y, 1);
        Add_Edge(y, x, 2);
    }
    memset(col, 0xff, sizeof col);
    LL ans = 0;
    for (int i = 1; i <= n; ++i) {
        if (vis[i]) continue;
        A = B = C = cnt = flag = 0;
        col[i] = 0;
        dfs(i);
        if (flag) ans += (A + B + C) * (A + B + C);
        else if (!A || !B || !C) ans += cnt;
        else ans += (A * B) + (B * C) + (A * C);
    }
    cout << ans << endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/Vexoben/p/11730087.html