CodeForces 1070F Katya and Segments Sets

CodeForces 1080F

https://codeforces.com/problemset/problem/1080/F

题目大意

\(n\) 个集合共 \(k\) 条线段, 每个线段有二个属性 \(l\) , \(r\) 属于集合 \(p\) , 给出 \(m\) 个询问, \(a\), \(b\), \(x\) , \(y\) 问是否对于每个集合 \(p \in [a, b]\) , 都满足存在至少一条线段 \((l, r)\) 满足 \(x \le l \le r \le y\) , 输出 yes 或 no 强制在线

数据范围

\(1 \le n, m \le 10^5, 1 \le k \le 3 \cdot 10^5\)
\(1 \le l \le r \le 10^9, 1 \le p \le n\)
\(1 \le a \le b \le n, 1 \le x \le y \le 10^9\)

解法

注意题目只需要输出 yes 或 no , 因此想必并不需要复杂的数据结构, 而询问可以从 \(x\) 优先考虑, 那么我们找到所有 \(l \ge x\) 的线段那么如果对于所有集合 \(p \in [a, b]\) , 都满足此时剩下线段中属于集合 \(p\) 的线段里存在 \(r \le y\) 则此集合满足条件
所以我们可以以 \(l\) 排序后对每个集合维护 \(r\) 的最小值 \(W\), 对于集合的区间维护 \(W\) 的最大值即可解决此题

Code

#include <algorithm>
#include <cstdio>
#include <iostream>

#define lson tr[u].ls, l, mid
#define rson tr[u].rs, mid + 1, r
using namespace std;

const int inf = 1e9 + 1;
int n, m, k, root[300050];
struct data
{
    int l, r, p;
    bool operator < (const data & other)
    {
        return l < other.l;
    }
} a[300050];
struct node
{
    int ls, rs;
    int mx;
}tr[9000050];
int tot;

inline void pushup(int u)
{
    tr[u].mx = max(tr[ tr[u].ls ].mx, tr[ tr[u].rs ].mx);
}
void newnode(int & u, int p)
{
    u = ++tot;
    tr[u] = tr[p];
}
void build(int & u, int l, int r)
{
    newnode(u, 0);
    if(l == r)
    {
        tr[u].mx = inf;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    pushup(u);
}
void ensert(int p, int & u, int l, int r, int qp, int qv)
{
    newnode(u, p);
    if(l == r)
    {
        tr[u].mx = min(tr[u].mx, qv);
        return;
    }
    int mid = (l + r) >> 1;
    if(qp <= mid) ensert(tr[u].ls, lson, qp, qv);
    else ensert(tr[u].rs, rson, qp, qv);
    pushup(u);
}
int query(int u, int l, int r, int ql, int qr)
{
    if(l == ql && r == qr)
    {
        return tr[u].mx;
    }
    int mid = (l + r) >> 1;
    if(qr <= mid) return query(lson, ql, qr);
    else if(ql > mid) return query(rson, ql, qr);
    else
    {
        int L = query(lson, ql, mid);
        int R = query(rson, mid + 1, qr);
        return max(L, R);
    }
}

int findpos(int x)
{
    int l = 1, r = k, res = k + 1;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(a[mid].l >= x) r = mid - 1, res = mid;
        else l = mid + 1;
    }
    return res;
}

int main()
{
    scanf("%d%d%d", & n, & m, & k);
    for(int i = 1; i <= k; ++i)
    {
        scanf("%d%d%d", & a[i].l, & a[i].r, & a[i].p);
    }
    sort(a + 1, a + k + 1);
    build(root[k + 1], 1, n);
    for(int i = k; i >= 1; --i)
    {
        ensert(root[i + 1], root[i], 1, n, a[i].p, a[i].r);
    }
    for(int i = 1; i <= m; ++i)
    {
        int a, b, x, y;
        scanf("%d%d%d%d", & a, & b, & x, & y);
        puts(query(root[findpos(x)], 1, n, a, b) <= y ? "yes" : "no");
        fflush(stdout);
    }
    return 0;
}

posted @ 2018-12-01 08:38  LJZ_C  阅读(186)  评论(0编辑  收藏  举报