五福街是一条笔直的道路,这条道路能够当作一个数轴,街上每一个建筑物的坐标均可以用一个整数来表示。小明是一位时光旅行者,他知道在这条街上,在过去如今和将来共有 \(n\) 个商店出现。第 \(i\) 个商店可使用四个整数 \(x_i, t_i, a_i, b_i\) 描述,它们分别表示:商店的坐标、商店的类型、商店开业的年份、商店关闭的年份。node
小明但愿经过时光旅行,选择一个合适的时间,住在五福街上的某个地方。他给出了一份他可能选择的列表,上面包括了 \(q\) 个询问,每一个询问用二元组(坐标,时间)表示。第 \(i\) 对二元组用两个整数 \(l_i, y_i\) 描述,分别表示选择的地点 \(l_i\) 和年份 \(y_i\) 。c++
如今,他想计算出在这些时间和地点居住的生活质量。他定义居住的不方便指数为:在居住的年份,离居住点最远的商店类型到居住点的距离。类型 \(t\) 的商店到居住点的距离定义为:在指定的年份,类型 \(t\) 的全部营业的商店中,到居住点距离最近的一家到居住点的距离。咱们说编号为 \(i\) 的商店在第 \(y\) 年在营业当且仅当 \(a_i \leq y \leq b_i\) 。注意,在某些年份中,可能在五福街上并不是全部 \(k\) 种类型的商店都有至少一家在营业。在这种状况下,不方便指数定义为 −1。你的任务是帮助小明求出每对(坐标,时间)二元组居住的不方便指数。api
第一行包含三个整数 \(n\) , \(k\) 和 \(q\),分别表示商店的数量、商店类型的数量和(坐标,时间)二元组的数量。\((1\leq n,q\leq 3\times 10^5,1\leq k \leq n)\)app
接下来 \(n\) 行,每行包含四个整数 \(x_i, t_i, a_i\), 和 \(b_i\) 用于描述一家商店,意义如题面所述\((1\leq x_i,a_i,b_i \leq 10^9,1\leq t_i \leq k,a_i \leq b_i)\)spa
接下来 \(q\) 行,每行包含两个整数 \(l_i\), 和 \(y_i\) ,表示一组(坐标,时间)查询\((1\leq l_i,y_i \leq 10^8)\)code
对于每组询问输出一个整数,包含\(q\)个整数,依次表示对于 \(q\) 组(坐标,时间)询问求出的结果。排序
子任务 1(5 分):\(n,q\leq 400\)get
子任务 2(7 分):\(n,q\leq 6\times 10^4,k\leq 400\)it
子任务 3(10 分):\(n,q\leq 3\times 10^5\),对于全部的商店\(a_i=1,b_i=10^8\)io
子任务 4(23 分):\(n,q\leq 3\times 10^5\),对于全部的商店\(a_i=1\)
子任务 5(35 分):\(n,q\leq 6\times 10^4\)
子任务 6(20 分):\(n,q\leq 3\times 10^5\)
先按时间排序,而后一个房子会加入一次,删除一次。
询问的时候能够二分一个答案。假设位置是\(x\),二分的答案是\(mid\),那么若是\([l-mid,l+mid]\)之间\(k\)种商店都出现了则是一个合法状况。咱们对每一个商店,记录与它种类相同的前一个商店\(pre_i\)。若是坐标在\([l+mid+1,\infty]\)之间的全部商店知足\(pre_i\geq l-mid\),那么就合法,不然必定不合法。因此咱们要维护区间全部商店的\(pre\)的最小值。
由于还有删除操做,全部对于线段树上每一个点开一个\(multiset\)。
把坐标离散一下(其实也能够不离散),再对于每一个种类加入坐标\(-\infty\)和\(\infty\)。
复杂度瓶颈\(O(Mlog^2N)\),其实能够将二分变成线段树上二分作到一个\(log\)。
代码:
#include<bits/stdc++.h> #define ll long long #define N 300005 using namespace std; inline int Get() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while('0'<=ch&&ch<='9') { x=(x<<1)+(x<<3)+ch-'0'; ch=getchar(); } return x*f; } int n,k,m; struct house { int x,t,a,b; }s[N]; struct query { int x,t; }q[N]; int T; vector<ll>P; int Find(ll p) {return upper_bound(P.begin(),P.end(),p)-P.begin()-1;} const ll INF=2e9+233; void discrete() { static vector<int>d; for(int i=1;i<=n;i++) { d.push_back(s[i].a); d.push_back(s[i].b); P.push_back(s[i].x); } for(int i=1;i<=m;i++) d.push_back(q[i].t); P.push_back(INF),P.push_back(-INF); sort(d.begin(),d.end()); d.resize(unique(d.begin(),d.end())-d.begin()); sort(P.begin(),P.end()); P.resize(unique(P.begin(),P.end())-P.begin()); T=d.size(); for(int i=1;i<=n;i++) { s[i].a=lower_bound(d.begin(),d.end(),s[i].a)-d.begin()+1; s[i].b=lower_bound(d.begin(),d.end(),s[i].b)-d.begin()+1; s[i].x=lower_bound(P.begin(),P.end(),s[i].x)-P.begin(); } for(int i=1;i<=m;i++) { q[i].t=lower_bound(d.begin(),d.end(),q[i].t)-d.begin()+1; } } int rt; int ls[N*8],rs[N*8]; int lx=1,rx=1e9; multiset<int>::iterator it; multiset<int>st[N*8]; int mn[N*8]; int tot; #define mp(a,b) make_pair(a,b) #define pr pair<int,int> vector<pr>add[N<<2],del[N<<2]; vector<pr>que[N<<2]; int size[N],appear; int ans[N]; int New() { ++tot; mn[tot]=P.size()-1; return tot; } void update(int v) { int L=ls[v]?mn[ls[v]]:P.size()-1; int R=rs[v]?mn[rs[v]]:P.size()-1; mn[v]=min(L,R); } void Insert(int &v,int lx,int rx,int p,int val,int flag) { if(!v) v=New(); if(lx==rx) { if(flag==1) { st[v].insert(val); } else { st[v].erase(st[v].find(val)); } if(st[v].size()) mn[v]=*st[v].begin(); else mn[v]=P.size()-1; return ; } int mid=lx+rx>>1; if(p<=mid) Insert(ls[v],lx,mid,p,val,flag); else Insert(rs[v],mid+1,rx,p,val,flag); update(v); } int query(int v,int lx,int rx,int l,int r) { if(!v) return P.size()-1; int ans=mn[v]; if(l<=lx&&rx<=r) { return ans; } int mid=lx+rx>>1; if(r<=mid) return query(ls[v],lx,mid,l,r); else if(l>mid) return query(rs[v],mid+1,rx,l,r); else return min(query(ls[v],lx,mid,l,r),query(rs[v],mid+1,rx,l,r)); } struct node { multiset<int>pos; void Get_segment(ll l,ll r,int flag) { Insert(rt,lx,rx,r,l,flag); } void Add(int p) { if(pos.find(p)==pos.end()) { it=pos.lower_bound(p); int r=*it; int l=*(--it); Get_segment(l,r,-1); Get_segment(l,p,1); Get_segment(p,r,1); } pos.insert(p); } void Del(int p) { pos.erase(pos.find(p)); if(pos.find(p)==pos.end()) { it=pos.lower_bound(p); ll r=*it; ll l=*(--it); Get_segment(l,p,-1); Get_segment(p,r,-1); Get_segment(l,r,1); } } void Init() { pos.insert(0); pos.insert(P.size()-1); Get_segment(0,P.size()-1,1); } }coor[N]; int solve(int p) { int l=0,r=1e9,mid; while(l<r) { mid=l+r>>1; int R=lower_bound(P.begin(),P.end(),p+mid+1)-P.begin(); if(P[query(rt,lx,rx,R,P.size()-1)]>=p-mid) r=mid; else l=mid+1; } return l; } int main() { n=Get(),k=Get(),m=Get(); for(int i=1;i<=n;i++) { s[i].x=Get(); s[i].t=Get(); s[i].a=Get(); s[i].b=Get(); } for(int i=1;i<=m;i++) { q[i].x=Get(),q[i].t=Get(); } discrete(); lx=0,rx=P.size()-1; for(int i=1;i<=n;i++) { add[s[i].a].push_back(mp(s[i].x,s[i].t)); del[s[i].b].push_back(mp(s[i].x,s[i].t)); } for(int i=1;i<=m;i++) { que[q[i].t].push_back(mp(q[i].x,i)); } for(int i=1;i<=k;i++) coor[i].Init(); for(int i=1;i<=T;i++) { for(int j=0;j<add[i].size();j++) { size[add[i][j].second]++; if(size[add[i][j].second]==1) appear++; coor[add[i][j].second].Add(add[i][j].first); } if(appear<k) { for(int j=0;j<que[i].size();j++) { ans[que[i][j].second]=-1; } } else { for(int j=0;j<que[i].size();j++) { ans[que[i][j].second]=solve(que[i][j].first); } } for(int j=0;j<del[i].size();j++) { size[del[i][j].second]--; if(size[del[i][j].second]==0) appear--; coor[del[i][j].second].Del(del[i][j].first); } } for(int i=1;i<=m;i++) { cout<<ans[i]<<"\n"; } return 0; }