D - Good Tuple Problem
tag:并查集
类似题目:
错误原因:
在更新儿子节点的距离的时候,是直接进行更新,这是错误操作,应该先对父节点进行一次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;
}