A Eshag Loves Big Arrays

题目大意

给定一个长度为 n 的正整数数组 a ,现在可执行若干次操作(可为 0)

具体操作为:选定某个序列,删除严格大于序列的平均数的元素

请问最多能删去多少个元素

主要思路

最多能删去除最小值元素以外的所有元素,所以统计最小值个数即可

  1. #include <iostream>
  2. #include <cstring>
  3. #include <string>
  4. #include <algorithm>
  5. #include <stack>
  6. #include <string>
  7. #include <unordered_map>
  8. #include <set>
  9. #include <queue>
  10. using namespace std;
  11. #define int long long
  12. #define debug(a) cout << #a << " = " << a << endl;
  13. #define x first
  14. #define y second
  15. typedef pair<int, int> P;
  16. const int N = 200010;
  17. int n, a[N];
  18. int st[N];
  19. signed main(void)
  20. {
  21. ios::sync_with_stdio(false);
  22. int T;
  23. cin >> T;
  24. while(T--)
  25. {
  26. memset(st, 0, sizeof st);
  27. cin >> n;
  28. for(int i = 0; i < n; i++) cin >> a[i], st[a[i]]++;
  29. int maxa = 0, ans = 0;
  30. for(int i = 1; i <= 100; i++)
  31. {
  32. if(st[i])
  33. {
  34. maxa = st[i];
  35. break;
  36. }
  37. }
  38. cout << n - maxa << endl;
  39. }
  40. return 0;
  41. }

B Sifid and Strange Subsequences

题目大意

先有一个长度为 n 的数组,定义“奇怪数组”:数组中任意两个元素的绝对值差值大于等于数组中的最大值,即 |ai−aj|>=Max ,请问由原数组中最大能选出多少个元素构成“奇怪数组”

主要思路

首先先找性质,发现该数列至多有一个正数,反证法假设该数列存在两个正数x, y那么|x - y|一定小于max(x, y),所以至多存在一个正数,所以我们先统计出小于等于0的数的个数,并且维护所有小于等于0的数差的最小值,判断最小的正数是否满足性质即可

  1. #include <iostream>
  2. #include <cstring>
  3. #include <string>
  4. #include <algorithm>
  5. #include <stack>
  6. #include <string>
  7. #include <unordered_map>
  8. #include <set>
  9. #include <queue>
  10. using namespace std;
  11. #define int long long
  12. #define debug(a) cout << #a << " = " << a << endl;
  13. #define x first
  14. #define y second
  15. typedef pair<int, int> P;
  16. const int N = 200010;
  17. int n, a[N];
  18. int st[N];
  19. int b[N];
  20. signed main(void)
  21. {
  22. ios::sync_with_stdio(false);
  23. int T;
  24. scanf("%lld", &T);
  25. while(T--)
  26. {
  27. memset(b, 0, sizeof(b));
  28. scanf("%lld", &n);
  29. int res = 0;
  30. int mina = 1e9+1;
  31. for(int i = 0; i < n; i++)
  32. {
  33. scanf("%lld", &a[i]);
  34. if(a[i] <= 0) b[res++] = a[i];
  35. else mina = min(mina, a[i]);
  36. }
  37. sort(b, b + res);
  38. int cnt = 1e9;
  39. for(int i = 1; i < res; i++) cnt = min(cnt, b[i] - b[i - 1]);
  40. if(cnt >= mina && res < n) res++;
  41. printf("%lld\n", res);
  42. }
  43. return 0;
  44. }

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这个点选取右端点且由后面子树更新的最大值。

  1. #include <iostream>
  2. #include <cstring>
  3. #include <string>
  4. #include <algorithm>
  5. #include <stack>
  6. #include <string>
  7. #include <unordered_map>
  8. #include <set>
  9. using namespace std;
  10. #define int long long
  11. const int N = 1e6 + 50;
  12. typedef long long LL;
  13. int e[N], ne[N], h[N], idx;
  14. void add(int a, int b)
  15. {
  16. e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
  17. }
  18. int l[N], r[N];
  19. int t, n;
  20. int dp[N][2];
  21. void dfs(int u, int father)
  22. {
  23. for(int i = h[u]; ~i; i = ne[i])
  24. {
  25. int j = e[i];
  26. if(j == father) continue;
  27. dfs(j, u);//递归,由子树更新父元素
  28. dp[u][0] += max(dp[j][0] + abs(l[u] - l[j]), dp[j][1] + abs(l[u] - r[j]));
  29. dp[u][1] += max(dp[j][0] + abs(r[u] - l[j]), dp[j][1] + abs(r[u] - r[j]));
  30. }
  31. }
  32. signed main()
  33. {
  34. cin >> t;
  35. while (t -- ) {
  36. memset(h, -1, sizeof h);
  37. memset(dp, 0, sizeof dp);
  38. scanf("%lld", &n);
  39. for (int i = 1; i <= n; i ++ ) scanf("%lld%lld", &l[i], &r[i]);
  40. for (int i = 0; i < n - 1; i ++ ) {
  41. int a, b;
  42. scanf("%lld%lld", &a, &b);
  43. add(a, b);
  44. add(b, a);
  45. }
  46. dfs(1, -1);
  47. printf("%lld\n", max(dp[1][0], dp[1][1]));
  48. }
  49. return 0;
  50. }

D Kavi on Pairing Duty

给你一个长度n,数轴上有2n个点,定义一个好的配对,满足一下两个条件中一个即可:

  • 其中一部分A和B完全位于另一部分内部。
  • A和B长度相同。

问长度为n时,好的配对数量是多少

主要思路

设 dpi 为 2i点的良好配对数。
显然,答案是 dpn 。

dp[i] = i的约数+dp前i-1个数的和

当所有区间长度相同时,方案数是i的约数

当所有区间长度不同时,由不同长度的方案转移到长度为i的方案一定都不相同

  1. #include <iostream>
  2. #include <cstring>
  3. #include <string>
  4. #include <algorithm>
  5. #include <stack>
  6. #include <string>
  7. #include <unordered_map>
  8. #include <set>
  9. #include <queue>
  10. using namespace std;
  11. #define int long long
  12. #define debug(a) cout << #a << " = " << a << endl;
  13. #define x first
  14. #define y second
  15. typedef pair<int, int> P;
  16. const int N = 1000010, mod = 998244353;
  17. int n, dp[N];
  18. signed main(void)
  19. {
  20. ios::sync_with_stdio(false);
  21. cin >> n;
  22. for(int i = 1; i <= n; i++)//计算i这个数是哪个数的约数
  23. {
  24. for(int j = i; j <= n; j += i) dp[j]++;
  25. }
  26. //刚开始dp[i]表示i这个数的约数个数
  27. int s = 0;//初始化从1开始dp[i]的和
  28. dp[0] = 1;//初始化dp[0] = 1
  29. for(int i = 1; i <= n; i++)
  30. {
  31. dp[i] = (dp[i] + s) % mod;
  32. s = (s + dp[i]) % mod;
  33. }
  34. cout << dp[n] << endl;
  35. return 0;
  36. }