ABC327 D-E

比赛链接

D - Good Tuple Problem

tag:并查集

类似题目:

活动 - AcWingc

 错误原因:

在更新儿子节点的距离的时候,是直接进行更新,这是错误操作,应该先对父节点进行一次find,确保父节点更新为最终状态后,才能对其进行更新,否则就会出现,按照父节点的距离进行更新后,然后连到祖宗节点,这就会产生错误。

题解:

要想知道两个下标对应的数字是不是一样的,并且有多个限制,可以想到并查集操作,不同连通块肯定不会一样,如果处于相同的连通块,那么就看他们的距离是否为偶数,是偶数说明之前已经把他们固定为同一个数字了,如果现在还想把他们定为不同的数字,显然不可能。

// 加油昂!!!
// Problem: D - Good Tuple Problem
// Contest: AtCoder - HHKB Programming Contest 2023(AtCoder Beginner Contest 327)
// URL: https://atcoder.jp/contests/abc327/tasks/abc327_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
int d[N], p[N];
int find(int x)
{
    if (p[x] != x)
    {
        int t = find(p[x]);
        d[x] += d[p[x]];
        p[x] = t;
    }
    return p[x];
}
void solve()
{
    cin >> n >> m;
    vector<int> a(m), b(m);
    for (int i = 1; i <= n; i++)
    {
        p[i] = i;
    }
    for (int i = 0; i < m; i++)
    {
        cin >> a[i];
    }
    for (int i = 0; i < m; i++)
    {
        cin >> b[i];
    }
    for (int i = 0; i < m; i++)
    {
        int pa = find(a[i]), pb = find(b[i]);
        if (pa != pb) //确定了不在同一个连通块
        {
            p[pb] = p[pa];
            if ((d[b[i]] + d[a[i]]) % 2) d[pb] = 2;
            else d[pb] = 1;
        }
        else //在同一个
        {
            if (abs(d[a[i]] + d[b[i]]) % 2 != 1)
            {
                cout << "No";
                return ;
            }
        }
    }
    cout << "Yes";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

E - Maximize Rating

tag:DP

题解:

这个题其实还挺好想的,一看数据范围是5000,说明能进行n^2的操作,固定k的情况下,可以看成是对左边的分母求出最大值,对其可以看成是01背包变形,求出对于每一个k的分母最大值,再进行一遍循环按照公式求出最大值。

// 加油昂!!!
// Problem: E - Maximize Rating
// Contest: AtCoder - HHKB Programming Contest 2023(AtCoder Beginner Contest 327)
// URL: https://atcoder.jp/contests/abc327/tasks/abc327_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
double dp[5005];
double g[5005];
double s[5005];
void solve()
{
    cin >> n;
    vector<int> p(n + 1);
    g[0] = 1.0;
    for (int i = 1; i <= n; i++)
    {
        cin >> p[i];
        g[i] = g[i - 1] * 0.9;
        s[i] = s[i - 1] + g[i - 1];
    }
    for (int i = n; i >= 1; i--)
    {
        for (int k = n; k >= 1; k--)
        {
            if ((n - i + 1) > k)
                dp[k] = max(dp[k], dp[k - 1] + p[i] * g[k - 1]);
            else
                dp[k] += g[n - i] * p[i];
        }
    }
    double ans = dp[1] / s[1] - 1200; 
    for (int i = 2; i <= n; i++)
    {
        ans = max(ans, dp[i] / s[i] - 1200 / sqrt(i));
    }
    cout<< fixed << setprecision(15) << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nov-JovR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值