给出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;mapmp;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.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++; data[k].x.h[data[k].x.w]=op; sort(data[k].x.h+1,data[k].x.h+1+data[k].x.w); 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