安吉D3-T2
- 1安吉D19 T1
- 2安吉D19 T3
- 3安吉D20 模考12总结
- 4安吉D17 T3
- 5安吉D17 T4
- 6安吉D19 模考11总结
- 7安吉D15 A
- 8安吉D16 T4
- 9安吉D17 T1
- 10安吉D17 模考10总结
- 11安吉D16 T3
- 12安吉D16 模考9总结
- 13安吉D13 模考8总结
- 14安吉D13-T2
- 15安吉D13-T3
- 16安吉D12-T3
- 17安吉D11-B
- 18安吉D11-C
- 19安吉D11-D
- 20安吉D12 模考7总结
- 21安吉D12-T2
- 22安吉D11-A
- 23安吉D10 模考6总结
- 24安吉D10-T3
- 25安吉D10-T4
- 26安吉D8-E
- 27安吉D9-T4
- 28安吉D8-A
- 29安吉D8-B
- 30安吉D8-C
- 31安吉D8-D
- 32安吉D9 模考5总结
- 33安吉D9-T2
- 34安吉D9-T3
- 35安吉D6-T4
- 36安吉D4-G
- 37安吉D5-T2
- 38安吉D6 模考4总结
- 39安吉D6-T1
- 40安吉D6-T3
- 41安吉-开营测试 T4
- 42安吉D5 模考3总结
- 43安吉D5-T3
- 44安吉D4-A
- 45安吉D4-B
- 46安吉D4-C
- 47安吉D4:容斥原理
- 48安吉Day4-D
- 49安吉D3 模考2总结
- 50安吉D3-T1
- 51安吉D3-T2本文
- 52安吉D3-T4
- 53安吉D2 模考1总结
- 54安吉D2-T2
- 55安吉D1-G
- 56安吉D1-L
- 57安吉D2-T4
原题呈现
题目描述
巴蜀地区的地势非常崎岖,山峰耸立.我们将每座山峰依次编号为 到 ,第 座山峰的高度为 .
总共 支施工队,每支施工队的能力各不相同——有些擅长高空作业,有些擅长隧道构建.每支施工队有两个参数:
- :最高能施工的高度(即可以处理不超过该高度的山峰);
- :最长能修建的隧道长度(即最多可以连续炸掉 座山来修建隧道,因为出口和入口需要额外加固).
施工队需要从起点 出发,修建一条直达 的道路.我们规定 号和 号都是平地(高度为 ).
施工队可以从任意一个不超过最高施工高度的高度开始,修建一条高架和隧道结合的道路.一旦确定了道路的初始高度,整条道路的高度就不能再有任何变化.因此:
- 如果某座山峰的高度低于或等于施工高度,则只需正常修建高架即可;
- 如果某座山峰的高度高于施工高度,则必须炸山修隧道(即施工队需要在这座山上打通隧道).
请判断每支施工队是否能够胜任这项工作.
输入格式
第一行包含两个空格分隔的整数 和 . 第二行包含 个空格分隔的整数,其中第 个为 (第 座山峰的高度). 接下来 行,每行包含两个空格分隔的整数 和 ,代表第 支施工队的最大施工高度和最长隧道长度.
输出格式
输出共 行.第 行输出一个整数:如果第 支施工队能够胜任工作,则为 1,否则为 0.
样例
输入 #1
8 70 3 8 5 6 9 0 00 50 66 28 110 15 3150 7输出 #1
0110111数据范围
| 数据点 | 分值 | 限制 |
|---|---|---|
| 1 | 40 pts | , |
| 2 | 10 pts | 额外满足 且 |
| 3 | 100 pts | ,, |
题意可以理解为:求一段序列中一段最大的连续区间 ,满足: 内每一个数都大于 ,求 的大小 ,将其和 比大小,且多测.
考虑到每个施工队施工的高度越高,障碍越少,且消失的障碍不会回复,因而所需要的 也越少.
用一个更加形象的例子,现在有 道题, 个学生,每个学生有一个能力值 ,有一个耐力值 ,每道题有一个难度 ,现在,让每一名学生来做这些题目,若 使得 ,则这名学生做不出来第 道题,若有连续 道题这位学生都做不出来,这位学生就会崩溃,求这位学生会不会崩溃.
显然,如果学生 做不出来题目 ,那么能力弱于 的 也肯定做不出来题目 .
因此使用离线处理.将每一次询问(即每一个施工队)按 从高到低排序,将每一座山也按照高度从高到低排序.模拟一个收容山的并查集,用于记录已经对当前施工队产生影响的障碍,一开始,并查集为空,设未加入并查集且最高的山是第 座,高度为 ,则对于每一次询问:
- 检查 和 的大小关系
- 若当前询问的 比 大或等于(即第 座山,也就是未记录的最高的山都无法对该施工队增加障碍),跳过这个阶段.
- 否则,说明第 座山成为该施工队施工的新的障碍(由于施工队按照 从高到低排列,对靠前者造成影响的山,也会对靠后者造成影响),将 加入并查集,且与第 座和第 座(如果已经加入并查集的话)合并,并维护每个集合的左边界 和右边界 ,统计最大的区间 (初始由于没有山加入到并查集,所以是 0).重复这个操作,直到当前询问的 比 大或等于.
- 将 设置为 .
标程
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 100;int n, m, maxb, ans[N];
struct Mout { int h, id; friend bool operator<(const Mout a, const Mout b) { return a.h > b.h; }};
struct Team { int h, b, id; friend bool operator<(const Team a, const Team b) { return a.h > b.h; }};
struct Node { int fa, l, r;} d[N];
// 并查集struct DSU { Node *d; DSU(Node *d) : d(d) {}; // 将节点 x 加入到并查集之中 void active(int x) { d[x].fa = x; d[x].l = x, d[x].r = x; maxb = max(maxb, 1); } int find(int x) { if (d[x].fa == x) return x; d[x].fa = find(d[x].fa); return d[x].fa; } void merge(int a, int b) { a = find(a), b = find(b); if (a == b) return; d[a].fa = b; d[b].l = min(d[b].l, d[a].l); d[b].r = max(d[b].r, d[a].r); maxb = max(maxb, d[b].r - d[b].l + 1); }} dsu(d);
Mout h[N];Team a[N];int main() { freopen("mountain.in", "r", stdin); freopen("mountain.out", "w", stdout); cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> h[i].h; h[i].id = i; } for (int i = 1; i <= m; i++) { cin >> a[i].h >> a[i].b; a[i].id = i; } sort(h + 1, h + n + 1); sort(a + 1, a + m + 1); int ptr = 0; for (int i = 1; i <= m; i++) { int reqH = a[i].h; while (h[ptr + 1].h > reqH) { ptr++; int curId = h[ptr].id; dsu.active(curId); if (dsu.d[curId + 1].fa) dsu.merge(curId, curId + 1); if (dsu.d[curId - 1].fa) dsu.merge(curId, curId - 1); } ans[a[i].id] = ((maxb <= a[i].b - 1) ? 1 : 0); } for (int i = 1; i <= m; i++) { cout << ans[i] << endl; }}实际上,对于多次询问,若存在:
如果询问 中,元素 会对该询问的结果产生影响,那么对于所有弱于(或强于) 的 ,元素 会对该询问的结果产生影响.
可以考虑使用离线处理 + 排序解决,此时处理后者时可以保留对前者的影响.
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!


