Codeforces1080F. Katya and Segments Sets
阿新 • • 發佈:2018-12-03
Codeforces1080F. Katya and Segments Sets
題意:給定n個集合,每個集合裡有一些區間\([l_i,r_i]\),有m次詢問,每次詢問區間\([x,y]\)中,是否包含了集合a到集合b中每個集合至少一個區間。
做法:按區間右端點排序,從左到右建主席樹,維護每個集合最大的左端點的區間最小值,每次只需要查詢y對應的線段樹,詢問\([a,b]\)最小值,與x進行比較即可。
#include <bits/stdc++.h> typedef long long ll; using namespace std; int n, m, k; struct node{ int l, r, b; bool operator < (const node a) const { return r < a.r; } } a[301010], T[100010*100]; int rt[100010*100], tot; void ins(int &rt, int pre,int l,int r,int p,int d) { rt = ++tot; T[rt] = T[pre]; if(l == r) { T[rt].b = max(T[rt].b, d); return; } int mid = (l + r) >> 1; if(p <= mid) ins(T[rt].l, T[pre].l, l,mid, p,d); else ins(T[rt].r, T[pre].r, mid+1,r, p,d); T[rt].b = min(T[T[rt].l].b, T[T[rt].r].b); } int ask(int rt, int l, int r, int L, int R) { if(l == L && r == R) return T[rt].b; int mid = (l + r) >> 1; if(R <= mid) return ask(T[rt].l, l,mid, L,R); else if(L > mid) return ask(T[rt].r, mid+1,r, L,R); return min(ask(T[rt].l, l,mid, L,mid), ask(T[rt].r, mid+1,r, mid+1,R)); } vector<int> v; int fd(int x) { return upper_bound(v.begin(),v.end(),x) - v.begin(); } 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].b), v.push_back(a[i].r); sort(a+1, a+1+k); sort(v.begin(),v.end()); for(int i = 1; i <= k; ++i) ins(rt[i],rt[i-1], 1, n, a[i].b, a[i].l); for(int i = 1; i <= m; ++i) { int ta, b, x, y; scanf("%d%d%d%d",&ta,&b,&x,&y); int p = fd(y); if(ask(rt[p], 1, n, ta,b) >= x ) puts("yes"); else puts("no"); cout.flush(); } }