>Link
luogu P7913
>Description
n ≤ 1 0 5 n\le 10^5 n≤105
>解题思路
跟考场上的想法一样,不过那时候没学set,不知道怎么实现边删数边二分,然后就打了一个好麻烦的堆然后挂了TT set大法好(虽然说也有set以外的方法
根据题意,想到一种方法,先处理出 f i f_i fi 和 f f i ff_i ffi,分别表示国内/国际分到 i i i 个廊桥,停靠在廊桥的飞机数量
答案就为 m a x 1 ≤ i ≤ n f i + f f n − 1 max_{1\le i\le n}f_i+ff_{n-1} max1≤i≤nfi+ffn−1
然后转换题意,我们每新加一个廊桥,就是第一个原来没有廊桥停靠的飞机来停,它离开后第一个来到且也是原来没有廊桥停靠的飞机来停(先到先得)
然后可以直接用set保存目前没有廊桥停靠的飞机,一开始把所有区间转换成pair加进来,处理 f f f、 f f ff ff 时就是不断找出“子序列”并删除,找的过程可以用二分实现
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#define N 100010
using namespace std;
set<pair <int, int> > st;
int n, m1, m2, f[N], ff[N], ans;
int main()
{
// freopen ("P7913_9.in", "r", stdin);
scanf ("%d%d%d", &n, &m1, &m2);
int l, r;
for (int i = 1; i <= m1; i++)
{
scanf ("%d%d", &l, &r);
st.insert (make_pair (l, r));
}
set<pair <int, int> >::iterator now;
for (int i = 1; i <= n; i++)
{
f[i] = f[i - 1];
now = st.begin();
while (now != st.end())
{
f[i]++;
r = now -> second;
st.erase (now);
now = st.lower_bound (make_pair (r + 1, 0));
}
}
st.clear();
for (int i = 1; i <= m2; i++)
{
scanf ("%d%d", &l, &r);
st.insert (make_pair (l, r));
}
for (int i = 1; i <= n; i++)
{
ff[i] = ff[i - 1];
now = st.begin();
while (now != st.end())
{
ff[i]++;
r = now -> second;
st.erase (now);
now = st.lower_bound (make_pair (r + 1, 0));
}
}
for (int i = 0; i <= n; i++)
ans = max (ans, f[i] + ff[n - i]);
printf ("%d", ans);
return 0;
}