• 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;
    }
    
    
  • 相关阅读:
    函数
    数组
    类的例题
    异常语句
    类的学习
    for的穷举、迭代
    for循环
    switch case
    反相器,扇入扇出
    T触发器,JK触发器的verilog实现
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/10048173.html
Copyright © 2020-2023  润新知