A Eshag Loves Big Arrays
题目大意
给定一个长度为 n 的正整数数组 a ,现在可执行若干次操作(可为 0)
具体操作为:选定某个序列,删除严格大于序列的平均数的元素
请问最多能删去多少个元素
主要思路
最多能删去除最小值元素以外的所有元素,所以统计最小值个数即可
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <unordered_map>
#include <set>
#include <queue>
using namespace std;
#define int long long
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef pair<int, int> P;
const int N = 200010;
int n, a[N];
int st[N];
signed main(void)
{
ios::sync_with_stdio(false);
int T;
cin >> T;
while(T--)
{
memset(st, 0, sizeof st);
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i], st[a[i]]++;
int maxa = 0, ans = 0;
for(int i = 1; i <= 100; i++)
{
if(st[i])
{
maxa = st[i];
break;
}
}
cout << n - maxa << endl;
}
return 0;
}
B Sifid and Strange Subsequences
题目大意
先有一个长度为 n 的数组,定义“奇怪数组”:数组中任意两个元素的绝对值差值大于等于数组中的最大值,即 |ai−aj|>=Max ,请问由原数组中最大能选出多少个元素构成“奇怪数组”
主要思路
首先先找性质,发现该数列至多有一个正数,反证法假设该数列存在两个正数x, y那么|x - y|一定小于max(x, y),所以至多存在一个正数,所以我们先统计出小于等于0的数的个数,并且维护所有小于等于0的数差的最小值,判断最小的正数是否满足性质即可
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <unordered_map>
#include <set>
#include <queue>
using namespace std;
#define int long long
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef pair<int, int> P;
const int N = 200010;
int n, a[N];
int st[N];
int b[N];
signed main(void)
{
ios::sync_with_stdio(false);
int T;
scanf("%lld", &T);
while(T--)
{
memset(b, 0, sizeof(b));
scanf("%lld", &n);
int res = 0;
int mina = 1e9+1;
for(int i = 0; i < n; i++)
{
scanf("%lld", &a[i]);
if(a[i] <= 0) b[res++] = a[i];
else mina = min(mina, a[i]);
}
sort(b, b + res);
int cnt = 1e9;
for(int i = 1; i < res; i++) cnt = min(cnt, b[i] - b[i - 1]);
if(cnt >= mina && res < n) res++;
printf("%lld\n", res);
}
return 0;
}
C Parsa’s Humongous Tree
题目大意
给你一棵树,树上的每个节点 i 都有一个值域 [li,ri] ,我们需要从值域中确定一个值 ai∈[li,ri] ,而 (u,v)(u,v) 边权值则为∣au−av∣ 。我们的目的就是要让所有的边权值之和最大。求出最大权值之和。
主要思路
树形dp,首先考虑性质,我们发现在中间的数不管选取区间内任意一个点与左右两点距离和都相同,所以我们只需考虑选取左端点和右端点,dp[i] [0]表示当前i这个点选取左端点且由后面子树更新的最大值,dp[i] [1]表示当前i这个点选取右端点且由后面子树更新的最大值。
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <unordered_map>
#include <set>
using namespace std;
#define int long long
const int N = 1e6 + 50;
typedef long long LL;
int e[N], ne[N], h[N], idx;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int l[N], r[N];
int t, n;
int dp[N][2];
void dfs(int u, int father)
{
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == father) continue;
dfs(j, u);//递归,由子树更新父元素
dp[u][0] += max(dp[j][0] + abs(l[u] - l[j]), dp[j][1] + abs(l[u] - r[j]));
dp[u][1] += max(dp[j][0] + abs(r[u] - l[j]), dp[j][1] + abs(r[u] - r[j]));
}
}
signed main()
{
cin >> t;
while (t -- ) {
memset(h, -1, sizeof h);
memset(dp, 0, sizeof dp);
scanf("%lld", &n);
for (int i = 1; i <= n; i ++ ) scanf("%lld%lld", &l[i], &r[i]);
for (int i = 0; i < n - 1; i ++ ) {
int a, b;
scanf("%lld%lld", &a, &b);
add(a, b);
add(b, a);
}
dfs(1, -1);
printf("%lld\n", max(dp[1][0], dp[1][1]));
}
return 0;
}
D Kavi on Pairing Duty
给你一个长度n,数轴上有2n个点,定义一个好的配对,满足一下两个条件中一个即可:
- 其中一部分A和B完全位于另一部分内部。
- A和B长度相同。
问长度为n时,好的配对数量是多少
主要思路
设 dpi 为 2i点的良好配对数。
显然,答案是 dpn 。
dp[i] = i的约数+dp前i-1个数的和
当所有区间长度相同时,方案数是i的约数
当所有区间长度不同时,由不同长度的方案转移到长度为i的方案一定都不相同

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <unordered_map>
#include <set>
#include <queue>
using namespace std;
#define int long long
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef pair<int, int> P;
const int N = 1000010, mod = 998244353;
int n, dp[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin >> n;
for(int i = 1; i <= n; i++)//计算i这个数是哪个数的约数
{
for(int j = i; j <= n; j += i) dp[j]++;
}
//刚开始dp[i]表示i这个数的约数个数
int s = 0;//初始化从1开始dp[i]的和
dp[0] = 1;//初始化dp[0] = 1
for(int i = 1; i <= n; i++)
{
dp[i] = (dp[i] + s) % mod;
s = (s + dp[i]) % mod;
}
cout << dp[n] << endl;
return 0;
}
本文深入探讨了数据结构和算法在解决复杂问题中的应用,重点分析了动态规划(Dynamic Programming)和树形动态规划(Tree DP)的实例。通过AEshagLovesBigArrays问题,展示了如何利用动态规划策略最多删除数组中的元素。接着,BSifidandStrangeSubsequences题目解释了如何找到满足特定条件的奇怪数组,关键在于理解问题特性并统计负数个数。在CParsa’sHumongousTree问题中,我们利用树形DP寻找树上节点值的最大边权和。最后,DKavionPairingDuty问题介绍了如何计算良好配对的数量,关键在于理解约数的概念和区间长度的匹配。这些案例揭示了动态规划和树形DP在解决实际问题中的强大能力。
394

被折叠的 条评论
为什么被折叠?



