230602 做题记录 // 儿童节快乐
一共有七块钱,花了两块买了一个我叶的吧唧。
为什么只买一个呢?因为剩下的几个长得还没我自己画的好看,,,
还有两块钱买了一个灯,剩下三块钱加入崩门,还有一块钱充公了。
你说,2 + 2 + 3 + 1 不是等于 8 吗?你猜 ~
A. Strange Way to Express Integers
http://222.180.160.110:1024/contest/3656/problem/1
B. 滑动窗口
http://222.180.160.110:1024/contest/3656/problem/2
字面意思。。。
namespace XSC062 {
using namespace fastIO;
const int maxn = 1e6 + 5;
int n, k, h, t;
int a[maxn], q[maxn];
int main() {
read(n), read(k);
h = 1, t = 0;
for (int i = 1; i <= n; ++i) {
read(a[i]);
if (h <= t && i - q[h] >= k)
++h;
while (h <= t && a[i] <= a[q[t]])
--t;
q[++t] = i;
if (i >= k)
print(a[q[h]], ' ');
}
putchar('\n');
h = 1, t = 0;
for (int i = 1; i <= n; ++i) {
if (h <= t && i - q[h] >= k)
++h;
while (h <= t && a[i] >= a[q[t]])
--t;
q[++t] = i;
if (i >= k)
print(a[q[h]], ' ');
}
return 0;
}
} // namespace XSC062
C. 工作安排
http://222.180.160.110:1024/contest/3656/problem/3
妙妙贪心题,想了好久好久。
不难发现被选中的 需要满足 。
然后下意识变形,得到 。
不难想到尝试枚举可能的 的值,并判断是否存在 个 ,使得 ,且对于 ,有 。
那光是枚举就会起飞,更何况还存在一个目测只能暴搜判定的 check。
这里有两个分化点:
-
若 ,且 ,那么明显有 。
这代表着什么呢? 对 的要求从 下降为了 。
那么 check 就会好判定很多了。
题外话:智力没悟到这个 trick 哈哈哈,我给他讲了半天他都是懵的,后来幡然醒悟气得差点从七楼跳下去哈哈哈
-
这个点有点抽象。不妨这么想:假设平面上有若干个起点相同的区间,区间 的范围为 ,赋予其权值为 。将这些区间按照长度从小到大排序。
那么待求就可以转化为,在数轴上寻找一个 ,满足存在 个右端点在 左边的区间,其权值和大于等于 。
一个很关键的 trick 就是, 一定会落在某个区间的右端点,即上图中的灰色分割线处。
为什么呢?对于 和 中间的部分,即任意两根相邻分割线中间的空白部分, 落在上面是没有意义的。从 区间 的右端点开始,一直到 区间 的右端点之前,右端点在 前面的区间都只有前 个,而当 越小时, 越容易满足,所以就选择可行范围内最小的 。
那么思路就出来了。我们把给定的区间按 从小到大排序,对于每一个 ,我们判定一下 是否大于等于 。
如果是,那么就会存在一组可行解,满足 。因为 越往后越大,我们只求最小的 ,所以输出第一个可行的 即可…… 真的是这样吗?
在前 个区间中,如果我们去除一个权值最小的区间, 仍有可能成立,去除了第二小、第三小…… 也都有可能。
所以我们用一个小根堆存储所有权值,只要 ,我们就不断弹出队头。
还没完。因为现在 不一定等于 了,所以得到的第一个可行解不一定就是最优解。所以我们要把所有 作为 的情况都过一遍。
那就又迎来了一个问题,假如我们在 时从优先队列中弹出了一些元素,但在 时不想弹出这些元素,怎么办呢?
也就是说,对于 ,存在 ,且 已被弹出。下证这种情况不可能成为最优解。
对于 ,假设答案为 ,那么这 个区间权值一定都大于等于 。既然要恢复 ,那么不可能抛弃权值更大的原先 个区间。即使抛弃了在 之后的所有区间,答案也是会比 大的。
题外话:这个 trick 我在 A 了过后写博客的时候才发现……
时间复杂度 ,其中 是排序。
#define int long long
namespace XSC062 {
using namespace fastIO;
const int inf = 1e18;
const int maxn = 5e5 + 5;
struct _ { int a, b; };
_ a[maxn];
int n, s, cnt, res = inf;
std::priority_queue<int, std::vector<int>,
std::greater<int> > q;
inline int min(int x, int y) {
return x < y ? x : y;
}
int main() {
read(n);
for (int i = 1; i <= n; ++i) {
read(a[i].a), read(a[i].b);
a[i].b += a[i].a;
}
std::sort(a + 1, a + n + 1,
[&](_ x, _ y) { return x.b < y.b; } );
for (int i = 1; i <= n; ++i) {
s += a[i].a;
q.push(a[i].a);
if (s >= a[i].b) {
while (q.size() && s - q.top() >= a[i].b)
s -= q.top(), q.pop(), ++cnt;
res = min(res, i - cnt);
}
}
if (res == inf)
puts("-1");
else print(res);
return 0;
}
} // namespace XSC062
#undef int
—— · EOF · ——
真的什么也不剩啦 😖
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本