[AGC040B] Two Contests

发布时间 2023-05-19 21:01:24作者: DCH233

[AGC040B] Two Contests

挺难的。首先有一个搞笑的想法,最长的一个区间单独划分一个集合,可扩展性不是很强。

猜一下最后可能是怎样的,我写了个按照 \(l\) 排序取前缀后缀,然后再结合上面的乱搞一下,只过了一半的点,不妙。

但是前缀后缀的思路还可以沿用,注意到写出来的式子里面有 \(l,r\) 两个参数,而且贡献很抽象,所以考虑转化一下贡献。

注意到所有 \(l\) 的最大值和所有 \(r\) 的最小值是特殊的两个量,我们可以利用这两个量具体地描绘贡献,假定这两个量不在同一个集合内,那么一个区间的两种贡献分别为 \(r - \max l + 1\)\(\min r - l + 1\)。然后就是经典的排序处理。

剩下只需处理这两个量在同一个集合内的划分,很显然剩下就取最长的区间即可。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

namespace IO {
#define isdigit(x) (x >= '0' && x <= '9')
template<typename T>
  inline void read(T &x) {
  x = 0; char ch = getchar(); int f = 0;
  for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  if(f) x = -x;
}
template<typename T, typename... Rest>
inline void read(T &x, Rest&... rest) {
   read(x), read(rest...);
}
template<typename T>
inline void write(T x) {
  if(x < 0) putchar('-'), x = -x;
  if(x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
#undef isdigit
}
using namespace IO;

constexpr int N = 1e5 + 10;
int n;
struct Itv {
  int l, r, a, b;
}a[N];
int suf[N];

int main() {
  read(n);
  for(int i = 1; i <= n; ++i)
    read(a[i].l, a[i].r);

  int u = 0, v = 0, ans = 0;
  a[0] = {0, 1000000000, 0, 0};
  for(int i = 1; i <= n; ++i) {
    if(a[i].l > a[u].l) u = i;
    if(a[i].r < a[v].r) v = i;
  }
  int mx = a[u].l, mn = a[v].r;
  for(int i = 1; i <= n; ++i)
    ans = max(ans, a[i].r - a[i].l + 1 + max(0, mn - mx + 1));

  for(int i = 1; i <= n; ++i)
    a[i].a = max(a[i].r - mx + 1, 0), a[i].b = max(mn - a[i].l + 1, 0);
  sort(a + 1, a + n + 1, [](Itv x, Itv y) {
    return x.a > y.a;
  });
  suf[n + 1] = 1e9;
  for(int i = n; i >= 1; --i)
    suf[i] = min(suf[i + 1], a[i].b);
  mn = 1e9;
  for(int i = 1; i < n; ++i) {
    mn = min(mn, a[i].a);
    ans = max(ans, mn + suf[i + 1]);
  }

  printf("%d\n",ans);
  return 0;
}