2019年9月21日シミュレーションゲーム

2019年9月21日シミュレーションゲーム

T1:奇妙なキュー

同様のブルーブックのアレイツリーの例の「アルゴリズムコンテストのステップアップガイド」。

誰もがこの問題を開始することが容易となり、高さによって最初の並べ替えを考えるのは難しいことではありません。

高さは、昇順にソートされ、順次キューの各位置を手配します。このように、している私たちは、X-個人に彼の高さに配置していることを前提と数字を覚えている(A_X \)\、\ (B_X \)今、すべての人の身長キュー位置により大きい惜しま、\(A_Xを\)、X-1が、パーソナル位置の高さにスケジュールされた未満である\(A_X \)

質問へ:前または後に、この位置を満たすために位置占有されておらず、まさにこの位置を見つけるために(b_x \)\欠員。ロケーションは、1ギャップ(占有されていない)、0が占有さを表す0/1を占有することができません。個別のx位置場合、これは、使用/サフィックスを示す前であってもよい\(POS_Xの\)正確前\(B_X \)空孔、および\(POS_Xの\)自体は、プレフィックスの位置、次いで、空間である\(SUM_X B_X + 1 = \)および接尾辞が使用可能な共感を示して\(POS_Xの\)を正確にした後、\(B_X \)は、ケースを空孔。しかし同時に、フロントを維持し、サフィックスはあまりにも面倒なので、試してみて、接頭辞を表す\(POS_Xの\)を正確にした後、\(b_x \)空孔の状況:X-1の個人的な位置が配置されており、今がありますされています前に、N-X +1スペース、\(POS_X \)が後\(B_X \)空孔、位置及び接頭辞である\(= N-SUM_X。1-X-B_X + \)

01および配列プレフィックスを非減少ので、我々は2つの点が満足見つけることができる(POS_Xの\)\の位置、サブ\(POS_Xの\)フロント/リア\(B_X \)個人の両方の場合、要求の辞書最小被験者、我々は二つの位置は、位置の正面を選択できるようにする際、昇順にソートされています。

私たちは、個々のx位置を手配するたびに、変更されることに注意してください\(POS_Xの\)の位置の動的配列を必要とし、接頭辞01を維持0/1状況を。私はメンテナンスフェンウィックの木、あなたが必要とするたびに選択した半分\(POS_X \)、2つのクエリプレフィックスとフェンウィックの木の上の総複雑さのそれぞれに割り当てられた値\(O(nlog ^ 2n個)\)

直接線分ツリー半部を使用してメンテナンスセグメントツリー01は、ツリー構造のための標準的なプロセスシーケンス、同様の文言平衡ツリー探索k番目の最大要素であり、そのような複雑さは、\(O(nlogn)\)

コード:

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5, inf = 0x3f3f3f3f;
int n, q[N], c[N];
pii p[N];
void add(int p, int v) {
    for(; p <= n; p += p & -p) c[p] += v;
}
int ask(int p) {
    int ans = 0;
    for(; p; p ^= p & -p) ans += c[p];
    return ans;
}
int calc(int v) {
    int l = 1, r = n, ans = n;
    while(l <= r) {
        int mid = (l + r) >> 1, res = ask(mid);
        if(res >= v) ans = min(ans, mid), r = mid - 1;
        else l = mid + 1;
    }
    return ask(ans) == v ? ans : inf;
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i].first, &p[i].second);
        add(i, 1);
    }
    sort(p + 1, p + n + 1);
    for(int i = 1; i <= n; ++i) {
        int pos = min(calc(p[i].second + 1), calc(n - i + 1 - p[i].second));
        if(pos == inf) return puts("impossible"), 0;
        q[pos] = p[i].first;
        add(pos, -1);
    }
    for(int i = 1; i <= n; ++i) printf("%d ", q[i]);
    return 0;
}

T2:素数

まず、状況の単一のセットを求めて考えます

呼び掛け結合R = 1E7を指摘、BOOL配列を直接要件を満たすために番号で標識することができます。素数を直接ことができる\(O(N)\)線形篩は、2つの素数の積で得られる、アレイ内の二十から二乗算プライムマークが得られる挙げることができます。複雑性分析:二重のループが表示され、実際には、内積は、すべての製品が合法である列挙するために、BREAK上の2つのRのサイクル数よりも大きく、2つの素数それぞれの製品は一度だけ列挙されています。だから、複雑さは超えていない\(O(N)を\)

ポリ問い合わせのためのBOOL配列\(O(n)が\)の配列を決定し、接頭辞、各\(O(1)\)質問。

コード:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 5;
int T, n, tot, l[N], r[N], p[N], sum[N];
bool mark[N], vis[N];
void prime() {
    for(int i = 2; i <= n; ++i) {
        if(!vis[i]) p[++tot] = i;
        for(int j = 1; j <= tot && i * p[j] <= n; ++j) {
            vis[i * p[j]] = true;
            if(i % p[j] == 0) break;
        }
    }
}
int main() {
    scanf("%d", &T);
    for(int i = 1; i <= T; ++i) {
        scanf("%d%d", &l[i], &r[i]);
        n = max(n, r[i]);
    }
    prime();
    for(int i = 1; i <= tot; ++i) {
        mark[p[i]] = true;
        for(int j = i; j <= tot; ++j) {
            if(1ll * p[i] * p[j] > n) break;
            mark[p[i] * p[j]] = true;
        }
    }
    for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + mark[i];
    for(int i = 1; i <= T; ++i) printf("%d\n", sum[r[i]] - sum[l[i] - 1]);
    return 0;
}

T3:良い記事

文字列のアルゴリズムは基本的に忘れ、およびハッシュを戦わなければなりませんでした。

アイデアは、ハッシュの文字列全体が非常に簡単であり、セットに挿入m個の文字のそれぞれのその後のハッシュ値と、出力サイズ、複雑さの最終セット\(O(nlogn)\)

データが大きく、カード、天然のオーバーフローを介して構築することができます。これは、ベースと、ハッシュ、最後の対比較型にある2つの大きな素数から選択デュアルモジュラスハッシュであってもよいです。

最初に関数パラメータの書き込みが二種類BOOL率を区別するために渡され、結果が送信パラメータ1及び図2に示すように、ハッシュの数に対応するシングルモード、WAページ全体が書き込まれます...

コード:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
const int N = 8e6 + 5;
const ll mod1 = 1e9 + 7, mod2 = 1e9 + 9, base1 = 131, base2 = 31;
int n, m;
ll hash1[N], hash2[N], fac_mod1[N], fac_mod2[N];
char s[N];
set<pll> U;
ll ask(int l, int r, bool op) {
    if(op == 1) return ((hash1[r] - hash1[l - 1] * fac_mod1[r - l + 1] % mod1) % mod1 + mod1) % mod1;
    else return ((hash2[r] - hash2[l - 1] * fac_mod2[r - l + 1] % mod2) % mod2 + mod2) % mod2;
}
int main() {
    scanf("%d%d%s", &n, &m, s + 1);
    fac_mod1[0] = fac_mod2[0] = 1;
    for(int i = 1; i <= n; ++i) {
        fac_mod1[i] = fac_mod1[i - 1] * base1 % mod1;
        fac_mod2[i] = fac_mod2[i - 1] * base2 % mod2;
    }
    for(int i = 1; i <= n; ++i) {
        hash1[i] = (hash1[i - 1] * base1 % mod1 + s[i] - 'a' + 1) % mod1;
        hash2[i] = (hash2[i - 1] * base2 % mod2 + s[i] - 'a' + 1) % mod2;
    }
    for(int i = 1; i + m - 1 <= n; ++i)
        U.insert(make_pair(ask(i, i + m - 1, 1), ask(i, i + m - 1, 0)));
    cout << U.size();
    return 0;
}

おすすめ

転載: www.cnblogs.com/yu-xing/p/11579951.html
おすすめ