「CF319E」ピンポン「ツリーライン」「互いに素セット。」

問題の意味

所定の間隔\((B)\ ) セクションに\((C、D)\ ) 場合に限り、エッジを持っている\(C <A <D \ ) または\(C <B <D \)

最初の間隔のセットで空です。そこ\(N- \)(\ (N- \のLeq 10 5 \)^)操作、フォームの各操作:

  • \(1 \) \(X- \) \(y軸の\)(\ ()| X- |、| y軸| \ leq10 ^ 9)\) 新しいセクションを追加する((X、Y)\)\を新しいことを確認してください、最長区間の長さ

  • \(2 \) \(X- \) \(y軸の\) 最初の問い合わせ\(私は\)最初のセクションに参加することを最初に到達することができます\(j個\)その合法的な問い合わせを確保するための最初の区間に参加するに

問題の解決策

二つのケースがあっても側面であると考えられる:最初のものは、大側へ少しでも含まれている、第二の交差があっても、双方向側を含まないです。

最後に、答えがより反映されませんのでご注意\(1 \)単方向のエッジを、我々は、双方向側を考えます。

それは双方向の側なので、我々は、通信ブロックを維持するために、ばらばらのセットを使用することができます。私たちはそれでも双方向レンジの側を考慮しなければならない新しい範囲のためのもの。

セグメントツリーは、これを行うために使用することができます。間隔に提供される\(\ \ログ)最後のセグメントツリーノードを。左右の端先送りに合流するすべてのパスのパスにルートノードに葉に対応するも、エッジラインを置くために新しいセクションを追加し、自分自身のタグに。最大従って新しいセクションを確保する制約の範囲の各加算の対象は含まれません。複雑さは、各区間のポイント正しい\(ログ\ \)セグメント、各々が一度削除参加しました。

彼は互いに素セット、またはYES、またはNOに包含関係を宣告するように頼みました。メンテナンスおよびR Lのために使用する通信ブロックは、文を含むことに留意されたいです。

時間複雑度\(O(N \アルファ( N)\ログn)\)

#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
struct node {
    int op, l, r;
} a[N];
int q, n, b[N * 2], f[N], L[N], R[N];
inline bool bel(int u, int l, int r) {
    return l < u && u < r;
}
int find(int u) {
    return u == f[u] ? u : f[u] = find(f[u]);
}
vector<int> vec[N << 2];
void solve(int u, int l, int r, int p, int cur) {
    if(vec[u].size()) {
        for(int i = 0; i < (int) vec[u].size(); i ++) {
            int v = vec[u][i]; v = find(v); f[v] = cur;
            L[cur] = min(L[cur], L[v]); R[cur] = max(R[cur], R[v]);
        }
        vec[u].clear();
        vec[u].push_back(cur);
    }
    if(l == r) return ;
    int mid = (l + r) >> 1;
    if(p <= mid) solve(u << 1, l, mid, p, cur);
    else solve(u << 1 | 1, mid + 1, r, p, cur);
}
void pushe(int u, int l, int r, int ql, int qr, int cur) {
    if(l == ql && r == qr) {
        vec[u].push_back(cur);
        return ;
    }
    int mid = (l + r) >> 1;
    if(qr <= mid) pushe(u << 1, l, mid, ql, qr, cur);
    else if(ql > mid) pushe(u << 1 | 1, mid + 1, r, ql, qr, cur);
    else {
        pushe(u << 1, l, mid, ql, mid, cur);
        pushe(u << 1 | 1, mid + 1, r, mid + 1, qr, cur);
    }
}
int main() {
    scanf("%d", &q);
    for(int i = 1; i <= q; i ++) {
        scanf("%d%d%d", &a[i].op, &a[i].l, &a[i].r);
        if(a[i].op == 1) {
            b[++ n] = a[i].l; b[++ n] = a[i].r;
        }
    }
    sort(b + 1, b + n + 1);
    n = unique(b + 1, b + n + 1) - b - 1;
    int c = 0;
    for(int i = 1; i <= q; i ++) {
        if(a[i].op == 1) {
            a[i].l = lower_bound(b + 1, b + n + 1, a[i].l) - b;
            a[i].r = lower_bound(b + 1, b + n + 1, a[i].r) - b;
            c ++; f[c] = c; L[c] = a[i].l; R[c] = a[i].r;
            solve(1, 1, n, a[i].l, c);
            solve(1, 1, n, a[i].r, c);
            if(a[i].l < a[i].r - 1) {
                pushe(1, 1, n, a[i].l + 1, a[i].r - 1, c);
            }
        }
        if(a[i].op == 2) {
            int u = find(a[i].l), v = find(a[i].r);
            bool tag = u == v || bel(L[u], L[v], R[v]) || bel(R[u], L[v], R[v]);
            puts(tag ? "YES" : "NO");
        }
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/hongzy/p/11715314.html