首页 > 其他分享 >[ARC147E] Examination

[ARC147E] Examination

时间:2023-03-23 17:13:49浏览次数:37  
标签:ch return int tr pos ARC147E inline Examination

[ARC147E] Examination

发现题解区和我做法都不一样,那就写一下吧。

首先判合法很显然把 \(A\) 和 \(B\) 都排序后依次比较即可。

首先转化成求最小的可以交换的集合。不难发现所有 \(B_i > A_i\) 的人都必须在这个集合内。接下来剩下的怎么取。

感觉很贪心,那么就按 \(B\) 从小到大遍历上述的人,考虑如何满足当前限制。注意到如果不使用其它人的 \(A\),那么我们只能使用还未使用的 \(A\) 中的最小值,所以考虑维护当前可用的 \(A\)。

如果此时最小的 \(A\) 无法满足限制,那么我们应该怎么办呢?肯定是用这个 \(A\) 去满足另外一些点的 \(B\),然后用这样的人对应的 \(A\) 来更新当前可用 \(A\) 的集合,不难发现一定会选可选的人中 \(A\) 最大的人。直到最小的可用的 \(A\) 能满足当前 \(B\) 的限制。

所以我们要做的就是:维护可用的 \(A\) 集合和最小值,并且查找 \(B\) 在某个范围内的 \(A\) 的最大值。前者可以用一个 std::multiset,后者可以写一个支持查询区间最大值和单点修改的线段树。复杂度就是 \(O(n \log n)\)

#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>
  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;

const int N = 3e5 + 10;

int n;
struct Score {
  int a, b;
  inline bool operator < (Score y) const {
    return b < y.b;
  }
}a[N];

multiset<int> s;

struct SegmentTree {
  #define lc (k << 1)
  #define rc (k << 1 | 1)
  #define mid (l + r >> 1)
  int tr[N << 2];
  inline void modify(int k, int l, int r, int pos) {
    if(l > pos || r < pos) return;
    if(l == r) return tr[k] = l, void();
    modify(lc, l, mid, pos), modify(rc, mid + 1, r, pos);
    tr[k] = a[tr[lc]].a > a[tr[rc]].a ? tr[lc] : tr[rc];
    return;
  }
  inline int query(int k, int l, int r, int L, int R) {
    if(r < L || R < l) return 0;
    if(L <= l && r <= R) return tr[k];
    int x = query(lc, l, mid, L, R), y = query(rc, mid + 1, r, L, R);
    if(a[x].a > a[y].a) return x;
    return y;
  }
}seg;

inline int find(int x) {
  int k = lower_bound(a + 1, a + n + 1, (Score){0, x + 1}) - a - 1;
  return seg.query(1, 1, n, 1, k);
}

int tmp1[N], tmp2[N];

int main() {
  read(n);
  for(int i = 1; i <= n; ++i)
    read(a[i].a), read(a[i].b), tmp1[i] = a[i].a, tmp2[i] = a[i].b;
  
  sort(tmp1 + 1, tmp1 + n + 1),
  sort(tmp2 + 1, tmp2 + n + 1);
  for(int i = 1; i <= n; ++i)
    if(tmp1[i] < tmp2[i]) {
      puts("-1");
      return 0;
    }

  sort(a + 1, a + n + 1, [](Score x, Score y) {
    return x.b < y.b;
  });

  int ans = 0;
  for(int i = 1; i <= n; ++i) {
    if(a[i].b > a[i].a) {
      ++ans, s.insert(a[i].a);
      a[i].a = -1;
    }
    seg.modify(1, 1, n, i);
  }

  for(int i = 1; i <= n; ++i) {
    if(a[i].b > a[i].a) {
      int x = *s.begin();
      while(x < a[i].b) {
        s.erase(s.begin());
        int p = find(x);
        s.insert(a[p].a);
        a[p].a = -1;
        seg.modify(1, 1, n, p);
        ++ans;
        x = *s.begin();
      }
      s.erase(s.begin());
    }
  } 
  printf("%d\n", n - ans);
  return 0;
}

标签:ch,return,int,tr,pos,ARC147E,inline,Examination
From: https://www.cnblogs.com/DCH233/p/17248156.html

相关文章

  • 【解题报告】Examination
    Examination本题解借鉴了这位dalao的思路看上去这题没人交题解,那我就来一发吧(弥天大雾传送门题意题目已经很简洁力分析一下一开始就不满足要求的话是肯定要交换的,......