1987. Nested Segments
Time limit: 1.0 second
Memory limit: 64 MB
You are given n segments on a straight line. For each pair of segments it is known that they either have no common points or all points of one segment belong to the second segment.
Then m queries follow. Each query represents a point on the line. For each query, your task is to find the segment of the minimum length, to which this point belongs.
Input
The first line contains an integer n that is the number of segments (1 ≤ n ≤ 105). i’th of the
next n lines contains integers ai and bi that are the
coordinates of endpoints of the i’th segment (1 ≤ ai < bi ≤
109). The segments are ordered by non-decreasing ai, and when ai = aj they
are ordered by decreasing length. All segments are distinct. The next line contains an integer m that is the number of queries (1 ≤ m ≤ 105). j’th of the
next m lines contains an integer cj that is the coordinate of the point (1 ≤ cj ≤
109). The queries are ordered by non-decreasing cj.
Output
For each query output the number of the corresponding segment on a single line. If the point does not belong to any segment, output “-1”. The segments are numbered from 1 to n in order they
are given in the input.
Sample
input | output |
---|---|
3 2 10 2 3 5 7 11 1 2 3 4 5 6 7 8 9 10 11 |
-1 2 2 1 3 3 3 1 1 1 -1 |
题意:
有n个段,编号1-n,每个段占据着a-b。 m个查询,查询c处所在的段中,长度最短的是几号段。如果没有段占据,输出-1。
首先把所有数字存在数组里,去离散化。然后把id按段的长度从长到短更新到树中。然后就查询固定的点在树中的ID的就行了。
#define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define LL int const int maxn = 811111; LL ID[maxn<<2];//记录该点属于哪一段 void PushUp(int rt) { if(ID[rt<<1] == ID[rt<<1|1]) ID[rt]=ID[rt<<1]; else ID[rt] = -1; } void PushDown(int rt,int m) { if(ID[rt]!=-1) { ID[rt<<1] = ID[rt]; ID[rt<<1|1] = ID[rt]; } } void build(int l,int r,int rt) { if (l == r) { ID[rt]=-1; return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int c,int l,int r,int rt) { if (L <= l && r <= R) { ID[rt] = c; return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , c , lson); if (m < R) update(L , R , c , rson); PushUp(rt); } LL query(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return ID[rt]; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; LL ret = 0; if (L <= m) ret += query(L , R , lson); if (m < R) ret += query(L , R , rson); return ret; } map<int ,int >my; struct bian { int l,r,len; int id; }; int num[800010];//用来记录输入的所有的数 用于去离散化 bian edge[100010]; int qus[100010];//记录询问 int cmp(bian a,bian b) { return a.len<b.len; } int arr[800010]; int main() { int i,a,b; int t,cas=1; int n; int ji; while(scanf("%d",&n)!=EOF) { my.clear(); ji=0; for(i=0;i<n;i++) { scanf("%d%d",&a,&b); edge[i].l=a; edge[i].r=b; edge[i].len=b-a; edge[i].id=i+1; num[ji++]=a; num[ji++]=b; } int m; scanf("%d",&m); for(i=0;i<m;i++) { scanf("%d",&qus[i]); num[ji++]=qus[i]; } sort(edge,edge+n,cmp); sort(num,num+ji); int ji2=1; for(i=1;i<ji;i++) { if(num[i]!=num[i-1]) num[ji2++]=num[i]; } ji=ji2; for(i=0;i<ji;i++) my[num[i]]=i+1; build(1,ji,1); for(i=n-1;i>=0;i--)//边长从大到小排序, 所以从后往前,边长短的会覆盖掉 { int l=my[edge[i].l]; int r=my[edge[i].r]; update(l,r,edge[i].id,1,ji,1); } for(i=0;i<m;i++) printf("%d\n",query(my[qus[i]],my[qus[i]],1,ji,1)); } return 0; }