复活了
CF 1942C1 Bessie’s Birthday Cake (Easy Version)
在所有点之内的三角形数量是 x-2
,之后判断每两个点之间间距,中间如果有一个点就加一个三角形
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int base = 131;
const int mod1 = 1e12 + 39;
const int mod2 = 1e9 + 9;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, x, y;
cin >> n >> x >> y;
vector<int> a(x);
for (int i = 0; i < x; i ++ ) cin >> a[i];
sort(a.begin(), a.end());
int ans = x - 2;
for (int i = 0; i < x; i ++ )
{
if (i == x - 1)
{
if (n - a[i] + a[0] - 1 == 1) ans ++ ;
}
else
{
if (a[i + 1] - a[i] == 2) ans ++ ;
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
CF 1942C2 Bessie’s Birthday Cake (Hard Version)
之前的思路还是和c1一样,不同的是,如果两个点之间的点数是奇数,那我们可以获得 2n + 1
个新三角形(每加一个点获得两个三角形,最后获得三个三角形),偶数的话只能获得 2n
(每加一个点获得两个三角形),所以优先选小的奇数
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int base = 131;
const int mod1 = 1e12 + 39;
const int mod2 = 1e9 + 9;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, x, y;
cin >> n >> x >> y;
vector<int> a(x);
for (int i = 0; i < x; i ++ ) cin >> a[i];
sort(a.begin(), a.end());
int ans = x - 2;
for (int i = 0; i < x; i ++ )
{
if (i == x - 1)
{
if (n - a[i] + a[0] - 1 == 1) ans ++ ;
}
else
{
if (a[i + 1] - a[i] == 2) ans ++ ;
}
}
vector<int> cnt1, cnt0;
for (int i = 0; i < x; i ++ )
{
if (i == x - 1)
{
if (n - a[i] + a[0] - 1 > 1)
{
if ((n - a[i] + a[0] - 1) % 2 == 0) cnt0.push_back((n - a[i] + a[0] - 1) / 2);
else cnt1.push_back((n - a[i] + a[0] - 1) / 2);
}
}
else
{
if (a[i + 1] - a[i] > 2)
{
if ((a[i + 1] - a[i] - 1) % 2 == 0) cnt0.push_back((a[i + 1] - a[i] - 1) / 2);
else cnt1.push_back((a[i + 1] - a[i] - 1) / 2);
}
}
}
sort(cnt1.begin(), cnt1.end());
for (auto t : cnt1)
{
if (y >= t)
{
ans += 2 * t + 1;
y -= t;
}
else
{
ans += 2 * y;
y = 0;
break;
}
}
for (auto t : cnt0)
{
if (y >= t)
{
ans += 2 * t;
y -= t;
}
else
{
ans += 2 * y;
y = 0;
break;
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
CF 1942D Learning to Paint
算是一个可以记录的trick
首先根据数据范围基本可以确定是一道dp
dp[i][j][0/1]
表示在前 i 个数中,第 j 大的情况是多少,最后一位 0/1 表示第 i 位是否是某一段的开头,如果取 0 的话,第 i 位没有要求,如果取 1 的话,第 i 位一定要是下一段的开头,也就是第 i - 1 位是不能选的
更新时,我们枚举最后一段的开头,然后把最大的情况存进优先队列 q.push({a[j][i] + dp[j - 1][1][0], j, 1});
,之后依次取出队头来更新 dp[i][j][1]
,并把原先次大的情况存进去(这里还没有完全理解)q.push({a[l][i] + dp[l - 1][key + 1][0], l, key + 1});
.,之后更新 dp[i][j][0]
,这个很容易理解看代码就行,最后输出也一样看代码就能理解
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int base = 131;
const int mod1 = 1e12 + 39;
const int mod2 = 1e9 + 9;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, k;
cin >> n >> k;
vector<vector<int>> a(n + 1, vector<int>(n + 1));
for (int i = 1; i <= n; i ++ )
{
for (int j = i; j <= n; j ++ )
{
cin >> a[i][j];
}
}
vector<vector<vector<int>>> dp(n + 1, vector<vector<int>>(k + 1, vector<int>(2)));
for (int i = 0; i <= n; i ++ )
{
for (int j = 1; j <= k; j ++ )
{
dp[i][j][0] = dp[i][j][1] = -INF;
}
}
dp[0][1][0] = 0;
for (int i = 1; i <= n; i ++ )
{
priority_queue<array<int, 3>> q;
for (int j = 1; j <= i; j ++ )
q.push({a[j][i] + dp[j - 1][1][0], j, 1});
for (int j = 1; j <= k; j ++ )
{
auto [v, l, key] = q.top();
q.pop();
dp[i][j][1] = v;
if (key + 1 <= k)
{
q.push({a[l][i] + dp[l - 1][key + 1][0], l, key + 1});
}
}
int p1 = 1, p2 = 1;
for (int j = 1; j <= k; j ++ )
{
if (dp[i - 1][p1][0] > dp[i - 1][p2][1])
dp[i][j][0] = dp[i - 1][p1 ++ ][0];
else dp[i][j][0] = dp[i - 1][p2 ++ ][1];
}
}
int p1 = 1, p2 = 1;
for (int i = 0; i < k; i ++ )
{
if (dp[n][p1][0] > dp[n][p2][1]) cout << dp[n][p1 ++ ][0] << ' ';
else cout << dp[n][p2 ++ ][1] << ' ';
}
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}