首页 > 代码库 > UVa 12715 Watching the Kangaroo(二分)
UVa 12715 Watching the Kangaroo(二分)
题意:n条线段(n <= 100000) (L<=R <= 1e9) ,m组询问(m <= 100000) 每次询问一个点的覆盖范围的最大值,一个点x对于一条包含其的线段,覆盖范围为min(x-L,R-x)
思路:考虑将线段一份为二,对于左边的那部分,以右端点排序,然后 二分找到右端点恰好满足的那个点为id,那么接下来要做的就是就是在[id,n]这个范围内找到L最小的那个点,可以通过求前缀最大来得到。那么左边最大距离为 seg[id].L-preLMax[id],右边最大的求法也是类似。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <string> #include <algorithm> #include <queue> #include <set> #include <map> using namespace std; typedef long long LL; const int maxn = 100000+10; #define REP(_,a,b) for(int _ = (a); _ <= (b); _++) struct seg{ int L,R; seg(int L = 0,int R = 0):L(L),R(R){} }; bool cmp1(seg a,seg b) { if(a.R != b.R) return a.R < b.R; else return a.L < b.L; } bool cmp2(seg a,seg b) { if(a.L != b.L) return a.L < b.L; else return a.R < b.R; } vector<seg>lft,rgt; int preLMax[maxn],preRMax[maxn]; int n,m; int main(){ int ncase,T=1; cin >> ncase; while(ncase--) { lft.clear(); rgt.clear(); scanf("%d%d",&n,&m); for(int i = 0; i < n; i++) { int L,R; scanf("%d%d",&L,&R); int mid = (L+R)>>1; lft.push_back(seg(L,mid)); rgt.push_back(seg(mid,R)); } sort(lft.begin(),lft.end(),cmp1); preLMax[lft.size()] = 1e9; for(int i = lft.size()-1; i >= 0; i--) { preLMax[i] = min(preLMax[i+1],lft[i].L); } sort(rgt.begin(),rgt.end(),cmp2); preRMax[0] = rgt[0].R; for(int i = 1; i < rgt.size(); i++) { preRMax[i] = max(preRMax[i-1],rgt[i].R); } printf("Case %d:\n",T++); while(m--) { int x,ans=0; scanf("%d",&x); int L = 0,R = lft.size()-1; while(L <= R) { int mid = (L+R) >>1; if(lft[mid].R < x) { L = mid+1; }else{ R = mid-1; } } ans = max(ans,x-preLMax[L]); L = 0,R = rgt.size()-1; while(L <= R) { int mid = (L+R) >>1; if(rgt[mid].L < x) { L = mid+1; }else{ R = mid-1; } } ans = max(ans,preRMax[R]-x); ans = max(ans,0); printf("%d\n",ans); } } return 0; }
UVa 12715 Watching the Kangaroo(二分)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。