今天这场有点狗运,C和D带点guess成分
但这些都得益于超✌的指导,让我茅塞顿开
(后面因为手贱重复提交罚时暴涨,我是傻逼)
感觉这场像AI一样,搁编译器里推了可长时间(
不过也是因为之前总是犯错,还没想明白就下手写代码,白白浪费罚时
也算是一种强制自己的方法
A
/*====================My_Solution====================//每次销毁垃圾都会导致剩下的*2我们要对每个垃圾的“次数”进行排序然后按次数从小到大去选择//====================My_Solution====================*/ void solve () {i64 n, c;std::cin >> n >> c;std::vector<i64> a(n + 1), b;std::set<int> st;for (int i = 1; i <= n; i++) {std::cin >> a[i];if (a[i] <= c) {b.push_back( std::__lg(c / a[i]) );}}std::sort(b.begin(), b.end());int cnt = 0;for (auto it : b) {if (cnt <= it) {cnt++;}}std::cout << n - cnt << '\n';
}
B
/*====================My_Solution====================//从双端队列中取数,使得构成的新数组中每一次都是符合要求的,即没有连续五个递增或递减的子序列如果原序列有序,那么我们可以轻易获得如果是乱序,先取大的,再取小的循环往复,即可获取答案//====================My_Solution====================*/ void solve () {int n;std::cin >> n;std::deque<int> p;std::vector<int> q;std::string ans = "";for (int i = 1; i <= n; i++) {int x;std::cin >> x;p.push_back(x);}int cnt = 1;while (p.size()) {if (cnt % 2 == 1) {int x = p.front();int y = p.back();q.push_back(x > y ? x : y);ans += x > y ? "L" : "R";x > y ? p.pop_front() : p.pop_back();} else {int x = p.front();int y = p.back();q.push_back(x < y ? x : y);ans += x < y ? "L" : "R";x < y ? p.pop_front() : p.pop_back();}cnt++;}std::cout << ans << '\n';
}
C
/*====================My_Solution====================//把全0数组变为目标数组操作方式是任意选一个数x(不小于数组的最小值)然后找到第一个a[i] < x,让a[i] += x以上视为一次操作先递增后递减的数组就是可以的吗?0 0 040 0 040 20 040 60 040 60 2040 60 也就是说,单纯递增也不一定满足要求如果某个数字大于等于数组最小值的两倍了,那就不可以了非递增的序列,显然是可以构造出来的我们的问题,仅在于是否能构造前端递增的序列4 5 6可以吗0 0 0 4 0 04 1 04 5 04 5 24 5 64 5 6 34 5 6 74 5 6 7 4我们可以看到,构造到8就不可以了也就是说,一段连续递增序列中不能有任意一个数字>= 2 * min(递增)不对,不是一定只能构造出先递增后递减的序列的5 2 2 30 0 0 05 0 0 05 2 0 0 5 2 2 05 2 2 15 2 2 3我们应当用f[i]表示第i位能构造出的最大数字则f[i] = 2 * min(1 ~ i-1) - 1//====================My_Solution====================*/ void solve () {int n;std::cin >> n;std::vector<i64> a(n + 1);std::vector<i64> premin(n + 1, INF);std::vector<i64> f(n + 1);for (int i = 1; i <= n; i++) {std::cin >> a[i];premin[i] = std::min(premin[i - 1], a[i]);}f[1] = a[1];for (int i = 2; i <= n; i++) {f[i] = 2 * premin[i - 1] - 1;if (a[i] > f[i]) {std::cout << "NO\n";return;}}std::cout << "YES\n";
}
D
/*====================My_Solution====================//给定一个排列,一定满足max(p[i], p[i + 1]) > p[i + 2]然后需要求所有[l, r]区间的最长递减子序列的长度之和??这个数据范围,O(n)或者O(logn)感觉O(logn)可以排除了,乱序的排列用不了二分,也没有二分答案我们只能从排列的性质入手,这个性质还是很有意思的也就是说,只要长度>= 3,最长递减子序列长度至少为2能不能考虑O(n)的dp呢最长递减子序列用dp是O(n ^ 2)的复杂度,能不能递推出来?f[i]表示第i位多出来的答案数,对于f[i]和f[i - 1],增加了[1, i] --> [i, i]总共i个区间观察1st样例1 2+1 3+2+1 == 101 3 6观察2nd样例1 2+1 3+2+1 3+2+1+1 == 17+2 +3 1 3 6 7观察3rd样例1 2+1 2+1+1 3+2+2+1 3+2+2+1+1 4+3+3+2+2+1+2 +2+2 +2+2+21 3 4 8 9 15最终答案就是:if a[i] < a[i - 1] f[i] = f[i - 1] + iif a[i] > a[i - 1] f[i] = f[i - 1] + 1 //====================My_Solution====================*/ void solve () {int n;std::cin >> n;std::vector<int> a(n + 1); std::vector<i64> f(n + 1);for (int i = 1; i <= n; i++) {std::cin >> a[i];}i64 ans = 1;f[1] = 1;for (int i = 2; i <= n; i++) {if (a[i] > a[i - 1]) {f[i] = f[i - 1] + 1;} else {f[i] = f[i - 1] + i;}ans += f[i];}std::cout << ans << '\n';
}