七夕祭プログラミングコンテスト問題

A. 神話キャラクター

解決アプローチ:各要素についてソート後の隣接要素を確認します。二分探索により位置を特定し、左右の値が条件を満たすか判定します。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define YES(x) (x ? "Yes" : "No")
const int MOD = 1e9 + 7;

int main_val[100005], backup_val[100005];

void process() {
    int N, count = 0;
    cin >> N;
    for(int i=0; i<N; i++) {
        cin >> main_val[i];
        backup_val[i] = main_val[i];
    }
    sort(main_val, main_val+N);
    
    for(int i=0; i<N; i++) {
        int X;
        cin >> X;
        int pos = lower_bound(main_val, main_val+N, backup_val[i]) - main_val;
        if((pos>0 && main_val[pos-1] >= backup_val[i]-X) || 
           (pos<N-1 && main_val[pos+1] <= backup_val[i]+X)) continue;
        count++;
    }
    cout << count << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    process();
    return 0;
}

B. ソーシャルネットワーク

数学的アプローチ:各ノードの友人関係を解析します。度数計算により効率的に処理し、最適化された方法で結果を導出します。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 200005;

vector<int> connections[MAXN];
int node_degree[MAXN];

void analyze() {
    int N;
    cin >> N;
    for(int i=1; i<N; i++) {
        int u, v;
        cin >> u >> v;
        connections[u-1].push_back(v-1);
        connections[v-1].push_back(u-1);
        node_degree[u-1]++;
        node_degree[v-1]++;
    }
    
    for(int i=0; i<N; i++) {
        int result = 0;
        for(auto neighbor: connections[i]) {
            result += connections[neighbor].size() - 1;
        }
        cout << result << ' ';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    analyze();
    return 0;
}

C. 結婚式の準備

最適化戦略:伴郎/伴娘の配置を差分に基づいてソートし、優先度付きキューを活用した効率的な選定を行います。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 200005;

int value_a[MAXN], value_b[MAXN];
priority_queue<int, vector<int>, greater<>> pq;
vector<int> sorted_indices;

void calculate() {
    int N, M;
    cin >> N >> M;
    for(int i=0; i<N+M+1; i++) cin >> value_a[i];
    for(int i=0; i<N+M+1; i++) {
        int b;
        cin >> b;
        value_a[i] -= b;
        sorted_indices.push_back(i);
    }
    
    sort(sorted_indices.begin(), sorted_indices.end(), [&](int x, int y){
        return value_a[x] > value_a[y];
    });
    
    ll total_sum = 0, selected_sum = 0;
    for(int i=0; i<N; i++) selected_sum += value_a[sorted_indices[i]];
    
    for(int i=0; i<N+M+1; i++) {
        if(i < N) {
            cout << total_sum - b[sorted_indices[i]] + selected_sum - value_a[sorted_indices[i]] + value_a[sorted_indices[N]] << ' ';
        } else {
            cout << total_sum - b[sorted_indices[i]] + selected_sum << ' ';
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    calculate();
    return 0;
}

D. 再会の確率

動的計画法アプローチ:各ステップでの状態遷移を前計算し、範囲指定に基づく効率的な合計計算を実行します。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 1e9 + 7;
const int MAXN = 100005;

ll dp[MAXN];

void solve() {
    int target, step;
    cin >> target >> step;
    dp[0] = 1;
    
    for(int i=1; i<=target; i++) {
        int low = max(0, i-step);
        dp[i+1] = (dp[low] + dp[i]) % MOD;
    }
    cout << dp[target+1] << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}

E. 城市探索

木構造の最適化:子ノードの情報を辞書木形式で管理し、ビット単位でのマッチング処理を実行します。葉ノードの特殊処理を考慮します。

タグ: Algorithm data-structures graph-theory dynamic-programming binary-search

8月10日 05:07 投稿