首页 > 代码库 > HDU 5107 线段树扫描线
HDU 5107 线段树扫描线
给出N个点(x,y),每个点有一个高度h
给出M次询问,问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10)
线段树扫描线
首先离散化Y坐标,以Y坐标建立线段树
对所有的点和询问进行离线操作,将询问和点按照x,y的大小排序,从左向右,从下向上,对于相同的(x,y)插入点在询问点之前
线段树的每个节点维护10个高度,每次询问[0,mark[i].y]的第mark[i].h高的值即可
#include "stdio.h" #include "string.h" #include "algorithm" #include "map" using namespace std; map<int,int>mp; struct Mark { int x,y,h,op,id; }mark[60010]; struct Ans { int w; // 记录共有多少个 int h[11]; }ans; struct node { int l,r; Ans x; }data[300010]; int y[60010],pri[30010]; bool cmp_mark(Mark a,Mark b) { if (a.x!=b.x) return a.x<b.x; else if (a.y!=b.y) return a.y<b.y; else return a.op<b.op; } Ans Merge(Ans a,Ans b) { int i,j,k; Ans c; i=j=k=1; while ((i<=a.w || j<=b.w) && k<=10) { if (j > b.w || (i <= a.w && a.h[i] < b.h[j]) ) c.h[k++] = a.h[i++]; else c.h[k++] = b.h[j++]; } c.w=k-1; return c; } void build(int l,int r,int k) { int mid; data[k].l=l; data[k].r=r; data[k].x.w=0; if(l==r) return ; mid=(l+r)/2; build(l,mid,k*2); build(mid+1,r,k*2+1); } void updata(int n,int op,int k) { int mid; if (data[k].l==n && data[k].r==n) { data[k].x.w=1; data[k].x.h[1]=op; return ; } mid=(data[k].l+data[k].r)/2; if (n<=mid) updata(n,op,k*2); else if (n>mid) updata(n,op,k*2+1); data[k].x=Merge(data[k*2].x,data[k*2+1].x); } Ans query(int l,int r,int k) { int mid; if (data[k].l==l && data[k].r==r) return data[k].x; mid=(data[k].l+data[k].r)/2; if (r<=mid) return query(l,r,k*2); else if (l>mid) return query(l,r,k*2+1); else return Merge(query(l,mid,k*2),query(mid+1,r,k*2+1)); } int main() { int n,m,i,cnt,temp; while (scanf("%d%d",&n,&m)!=EOF) { for (i=0;i<n;i++) { scanf("%d%d%d",&mark[i].x,&mark[i].y,&mark[i].h); y[i]=mark[i].y; mark[i].op=1; } for (i=n;i<n+m;i++) { scanf("%d%d%d",&mark[i].x,&mark[i].y,&mark[i].h); mark[i].id=i-n; y[i]=mark[i].y; mark[i].op=2; } cnt=n+m; sort(y,y+cnt); sort(mark,mark+cnt,cmp_mark); temp=unique(y,y+cnt)-y; // 离散化 for (i=0;i<temp;i++) mp[y[i]]=i; build(0,temp-1,1); for (i=0;i<cnt;i++) { if (mark[i].op==1) updata(mp[mark[i].y],mark[i].h,1); else { ans=query(0,mp[mark[i].y],1); // 询问返回该区间内前10个最小高度 if (mark[i].h<=ans.w) pri[mark[i].id]=ans.h[mark[i].h]; else pri[mark[i].id]=-1; } } for (i=0;i<m;i++) printf("%d\n",pri[i]); } return 0; }
HDU 5107 线段树扫描线
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。