【GDOI2015模拟12.21】鸡腿の乒乓

Description:

乒乓游戏可不是乒乓!乒乓好像也和这个游戏没啥关系。这个游戏的主角就是——区间。对于两个区间,如果(a,b)和(c,d)区间满足 c < a < d 或者 c < b < d ,就可以从(a,b)到(c,d)去。然后现在有两种操作,分别是:
1 x y : (x < y)表示在区间集合中添加(x,y)这个区间,保证新加入的区间长度一定比之前的所有区间长度长;
2 a b:(a≠b)表示询问是否有一条路从第a个区间到第b个区间。
鸡腿实在是智商捉急,请你来替他回答所有询问吧。一开始区间集合为空哦~

题解:

看错题爆零了,呜呜~~

如果相交的话是双向边。

包含的话是单向边。

并且一定是前面的被后面的包含(长度递增)。

双向边用并查集维护。

直接连边肯定是不行的,记住线段树这个好东西,打上标记,vector就是干。

那么查询是求y区间所在并查集能往左往右延伸到哪儿,如果与x区间又交,则有解。

Code:

#pragma GCC optimize(2)
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;

const int N = 1e5 + 5, M = 5e6 + 5, inf = 1e9 + 5;

int tq, Q, x, y, z, f[N], p[N], q[N];

struct node {
    int x, y;
} a[N];

struct tree {
    int l, r;
    vector<int> d;
} t[M]; int tot, pl, pr, px, g;

int find(int x) {return f[x] == x ? x : (f[x] = find(f[x]));}
void bin(int x, int y) {
    if(find(x) != find(y)) {
        p[f[y]] = min(p[f[y]], p[f[x]]);
        q[f[y]] = max(q[f[y]], q[f[x]]);
        f[f[x]] = f[y];
    }
}

void fi(int &i, int x, int y) {
    if(y < pl || x > pr || !i) return;
    int p = t[i].d.size();
    if(p) {
        fo(j, 0, p - 1) bin(px, t[i].d[j]);
        t[i].d.clear(); t[i].d.push_back(px);
    }
    if(x == y) return;
    int m = x + y >> 1;
    fi(t[i].l, x, m); fi(t[i].r, m + 1, y);
}

void add(int &i, int x, int y) {
    if(y < pl || x > pr) return;
    if(!i) i = ++ tot;
    if(x >= pl && y <= pr) {
        t[i].d.push_back(px);
        return;
    }
    int m = x + y >> 1;
    add(t[i].l, x, m); add(t[i].r, m + 1, y);
}

int main() {
    for(scanf("%d", &Q); Q; Q --) {
        scanf("%d %d %d", &z, &x, &y);
        if(z == 1) {
            a[++ tq].x = x; a[tq].y = y;
            p[tq] = x; q[tq] = y; f[tq] = tq;
            pl = pr = x; px = tq;
            fi(g, -inf, inf);
            pl = pr = y;
            fi(g, -inf, inf);
            pl = x + 1; pr = y - 1;
            add(g, -inf, inf);
        } else {
            if(find(x) == find(y)) printf("YES\n"); else {
                int u = p[f[y]], v = q[f[y]];
                if(a[x].x >= u && a[x].x <= v || a[x].y >= u && a[x].y <= v)
                    printf("YES\n"); else
                    printf("NO\n");
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/cold_chair/article/details/81021214