CodeForces 1070F Katya and Segments Sets
阿新 • • 發佈:2018-12-01
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; }