提高组初赛还是蛮难的,我压着56分的线过来的
1.廊桥分配
今年T1也是特别的水,导致后三题比较难
首先有一个关键结论:如果给廊桥编上号,每当一架飞机到达后,如果强制让它进入编号最小的廊桥,这样不会影响进入廊桥飞机的集合,且当廊桥总数增加后,原本在哪个廊桥的飞机,仍旧会进入原来的廊桥。
这个性质也很好理解:新加入廊桥可以视为原先的远机位的一部分,进入新加的这个廊桥的飞机可以视为在原来该进入远机位的飞机中贪心选择一轮。
至此本题已经有了优秀的解决方案:处理出每架飞机在廊桥充足的时候会进入哪个廊桥,然后在差分数组上统计一下即可。
考虑如何实现这个预处理过程:
考虑新建一个时间堆和空闲的编号堆,把所有的飞机按照到达时间排序,如果编号堆中有剩余就取出最小的编号,绑上这家飞机的离开时间扔进时间堆中,每当一架飞机进入之前,先把已经超过离开时间的飞机弹出,释放空闲的廊桥即可。
时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 1e5 + 5;
struct e {
int st, ed;
} a[Maxn];
bool cmp(e x, e y) {
return x.st < y.st;
}
std::priority_queue<int> hp_id;
std::priority_queue<std::pair<int, int> > hp_ed;
int n, m1, m2, ca[Maxn], cb[Maxn];
int main() {
scanf("%d%d%d", &n, &m1, &m2);
for(int i = 1; i <= m1; ++i) scanf("%d%d", &a[i].st, &a[i].ed);
std::sort(a + 1, a + m1 + 1, cmp);
for(int i = 1; i <= n; ++i) hp_id.push(-i);
for(int i = 1; i <= m1; ++i) {
if(!hp_ed.empty()) {
while(-hp_ed.top().first < a[i].st) {
hp_id.push(-hp_ed.top().second), hp_ed.pop();
if(hp_ed.empty()) break;
}
}
if(!hp_id.empty()) {
int x = -hp_id.top(); hp_id.pop();
ca[x]++; hp_ed.push(std::make_pair(-a[i].ed, x));
}
}
for(int i = 1; i <= n; ++i) ca[i] += ca[i - 1];
while(!hp_ed.empty()) hp_ed.pop(); while(!hp_id.empty()) hp_id.pop();
for(int i = 1; i <= m2; ++i) scanf("%d%d", &a[i].st, &a[i].ed);
std::sort(a + 1, a + m2 + 1, cmp);
for(int i = 1; i <= n; ++i) hp_id.push(-i);
for(int i = 1; i <= m2; ++i) {
if(!hp_ed.empty()) {
while(-hp_ed.top().first < a[i].st) {
hp_id.push(-hp_ed.top().second), hp_ed.pop();
if(hp_ed.empty()) break;
}
}
if(!hp_id.empty()) {
int x = -hp_id.top(); hp_id.pop();
cb[x]++; hp_ed.push(std::make_pair(-a[i].ed, x));
}
}
for(int i = 1; i <= n; ++i) cb[i] += cb[i - 1];
int mx_ans = 0;
for(int i = 0; i <= n; ++i) mx_ans = std::max(mx_ans, ca[i] + cb[n - i]);
printf("%d", mx_ans);
return 0;
}
2.括号序列
首先肯定是区间dp,令 表示从位置i到位置j一共的合法序列总情况数量。
但是不同的形态可能会有不同的转移,如:(S)
这种只能从S
转移过来等等。所以只开两维的dp状态必然是不够的。
直接将方法吧。将两位的dp扩充为三维,第三位表示不同的形态种类,dp状态就变成了 。没种状态表示:
-
: 形态如
***...*
的括号序列(即全部是*
)。 -
: 形态如
(...)
的括号序列(即左右直接被括号包裹且最左边括号与最右边的括号相互匹配)。 -
: 形态如
(...)**(...)***
的括号序列(即左边以括号序列开头,右边以*
结尾)。 -
: 形态如
(...)***(...)*(...)
的括号序列(即左边以括号序列开头,右边以括号序列结尾,注意:第2种形态也属于这种形态&