...

Educational Codeforces Round 47 (Rated for Div

Educational Codeforces Round 47 (Rated for Div. 2)

A. Game Shopping

​ 暴力模拟即可

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int n, m;
    cin >> n >> m;
    vector<int> arr(n + 1);
    for (int i = 1; i <= n; i++)cin >> arr[i];
    queue<int> q;
    for (int i = 1; i <= m; i++) {
        int x;
        cin >> x;
        q.push(x);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (q.empty())break;
        if (arr[i] <= q.front()) {
            ans++;
            q.pop();
        }
    }
    cout << ans << endl;
}

signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

B. Minimum Ternary String

​ 观察题目可以发现每次移动可以看作只有1在左右移动,0与2不能交换位置,所以最总答案是把所有1聚在一块原本0和2的位置不发生改变,于是问题变为把1插在哪里使得字符串字典序最小,显然插在第一个不是0的位置前即可

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    string s;
    cin >> s;

    string ans;

    int cnt = 0;
    for (auto c: s) {
        if (c == '1') ++cnt;
        else ans += c;
    }

    int n = ans.size();
    int pos = -1;
    while (pos + 1 < n && ans[pos + 1] == '0') ++pos;
    ans.insert(pos + 1, string(cnt, '1'));

    cout << ans << endl;
}

signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

C. Annoying Present

​ 由于每一个位置都会加上xi所以x与选择的位置没有关系,那么来讨论选择位置与di的关系。稍微计算一下可也得到

​ · 如果di0在数组的中点位置可以确保总和最大

​ · 如果di>0那么在数组的左右端点处可以确保总和最大

​ 由此可以得到结果

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int n, q;
    cin >> n >> q;
    int sum = 0;
    while (q--) {
        int x, d;
        cin >> x >> d;
        sum += x * n;
        if (d < 0) {
            int cnt = (n - 1) / 2;
            sum += (cnt * d + d) * cnt + (n % 2 == 0) * (cnt * d + d);
        } else {
            int cnt = n - 1;
            sum += (d + cnt * d) * cnt / 2;
        }
    }
    double ans = 1.0 * sum / n;
    cout << fixed << setprecision(12) << ans << endl;
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

D. Relatively Prime Graph

​ 首先观察数据发现n,m105由于边的上限是105那么简单打表一下可以发现当n=600,可以连的边就已经大于105了,而暴力枚举只需要n2的复杂度那么,如果对于所有数直接暴力枚举即可

​ 需要特判,如果边小于点的个数减一即m<n1那么无法构造出一个n点m边的图输出Impossible

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int n, m;
    cin >> n >> m;
    vector<PII > ans;
    if (m < n - 1) {
        puts("Impossible");
        return;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            if (__gcd(i, j) == 1)
                ans.push_back(make_pair(i, j));
            if (ans.size() == m)break;
        }
        if (ans.size() == m)break;
    }
    if (ans.size() == m) {
        cout << "Possible\n";
        for (auto [x, y]: ans)cout << x << ' ' << y << endl;
    } else cout << "Impossible\n";
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

E. Intercity Travelling

​ 题目中实际上每次是从1号点开始移动

​ 乘以2n1相当于把原本计算的期望的分母消了,所以计算所有可能得难度和即可

​ 设pos假设在pos点位置产生了ai的难度贡献,那么说明在(posi,pos)这个区间内不存在休息点而其余位置不管有没有休息点都可以那么对于每一个满足条件的pos,pos[i,n]都会产生ai的难度贡献,注意

​ ·当i=pos的时候区间左端点被固定,产生的贡献为ai2ni

​ ·当ipos的时候区间左右都没有被固定,但是需要排除i=pos的情况,所以产生的贡献就是ai(ni)2ni1

​ 综上答案通式为ans=i=1n(2ni+(ni)2ni1)ai

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'
const int mod = 998244353;

inline void solve() {
    int n;
    cin >> n;
    int ans = 0;
    vector<int> num(n + 1);
    num.front() = 1;
    for (int i = 1; i <= n; i++)num[i] = (num[i - 1] * 2) % mod;
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        ans = (ans + (num[n - i] + (n - i) * num[n - i - 1]) % mod * x % mod) % mod;
    }
    cout << ans << endl;
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

F. Dominant Indices

​ 题目大意为:给定一棵以1为根节点的有n个节点的树,设f(x,i)xxi,对于每个点求一个最小的k,使f(x,k)(1n106)

​ 暴力思想:用f[x][i]表示在x子树内与x距离为i的节点数,暴力枚举yson[x]f[y][i1]n2的复杂度会TLE

​ 用长链剖分进行优化

​ 1.先搜索重儿子,搜完一条链上的重儿子,回溯时,先让父节点继承重儿子答案,

​ 2.再搜索轻儿子,回溯时,暴力合并轻儿子上的信息,然后更新答案

​ 如果f开成N2空间会炸掉。可以巧妙的通过指针给每个节点动态分配内存才来解决这个问题

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'
const int mod = 998244353;
const int N = 1e6 + 7;
vector<int> e[N];
int son[N], len[N];
int buf[N], *f[N], *p = buf, ans[N];
//buf相当于f数组的第二维
//*f则是f数组的第一维
//f[i][j]第一维表示节点信息,第二维表示距离
void dfs(int x, int fa) {
    for (int y: e[x]) {
        if (y == fa)continue;
        dfs(y, x);
        if (len[son[x]] < len[y])son[x] = y;//dfs跑长儿子
    }
    len[x] = len[son[x]] + 1;
}

void dp(int x, int fa) {
    f[x][0] = 1;//到本身距离为0的点是本身
    if (son[x]) {//优先跑长链,后续答案向长链上合并
        f[son[x]] = f[x] + 1;//共享内存,拷贝数组
        dp(son[x], x);
        ans[x] = ans[son[x]] + 1;//继承长儿子节点答案
    }
    for (int y: e[x]) {
        if (y == fa || y == son[x])continue;
        f[y] = p,p += len[y];//给y开头的链申请空间
        dp(y, x);
        for (int j = 1; j <= len[y]; j++) {
            f[x][j] += f[y][j - 1];//累加所有子节点状态
            if (f[x][j] > f[x][ans[x]] || (f[x][j] == f[x][ans[x]] && j < ans[x]))//第一种为节点数更多,第二种则为k值更小
                ans[x] = j;
        }
    }
    if (f[x][ans[x]] == 1)ans[x] = 0;//唯一节点为本身
}

inline void solve() {
    int n;
    cin >> n;
    for (int i = 1; i < n; i++) {
        int x, y;
        cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs(1, 0);
    f[1] = p,p += len[1];//为根节点申请空间
    dp(1, 0);
    for (int i = 1; i <= n; i++)cout << ans[i] << "\n";
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

如有不懂请看董晓老师的b站视频讲解 D34【模板】长链剖分 CF1009F Dominant Indices

posted @   让你飞起来  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)
点击右上角即可分享
微信分享提示