牛客OI周赛4-提高组 C 战争(war)

战争(war)

思路:

二分答案, 找到第一个不满足条件的位置

首先对于一个值来说, 所有这个值的区间肯定有交区间, 然后在这个交区间内不能出现比它小的数

所以我们check时从大的值开始考虑, 求出交区间后并标记(用并查集), 如果之后的区间被标记过,那就说明有矛盾

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 5e5 + 10;
struct node {
    int l, r, p;
    bool operator < (const node & rhs) & {
        return p > rhs.p;
    }
}a[N], tmp[N];
int fa[N];
int Find(int x) {
    if(x == fa[x]) return x;
    else return fa[x] = Find(fa[x]);
}
int n;
bool check(int m) {
    for (int i = 1; i <= m; i++) tmp[i] = a[i];
    for (int i = 1; i <= n; i++) fa[i] = i;
    sort(tmp+1, tmp+1+m);
    for (int i = 1; i <= m; i++) {
        int j = i, l = tmp[i].l, r = tmp[i].r;
        while(j+1 <= m && tmp[j+1].p == tmp[i].p) {
            j++;
            l = max(l, tmp[j].l);
            r = min(r, tmp[j].r);
        }
        if(l > Find(r)) return false;
        while(r >= l) {
            if(fa[r] == r) fa[r] = Find(l-1), r--;
            else r = Find(r);
        }
        i = j;
    }
    return true;
}
int main() {
    int k;
    scanf("%d %d", &n, &k);
    for (int i = 1; i <= k; i++) {
        scanf("%d %d %d", &a[i].l, &a[i].r, &a[i].p);
    }
    int l = 1, r = k, m = l+r+1 >> 1;
    while(l < r) {
        if(check(m)) l = m;
        else r = m-1;
        m = l+r+1 >> 1;
    }
    printf("%d
", m+1);
    return 0;
}
原文地址:https://www.cnblogs.com/widsom/p/9877997.html