G. Nested Segments
Time limit: 1.0 second
Memory limit: 64 MB
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 ≤ 10
5).
i’th of the next
n lines contains integers
a
i and
b
i that are the coordinates of endpoints of the
i’th segment (1 ≤
a
i <
b
i ≤ 10
9). The segments are ordered by non-decreasing
a
i, and when
a
i =
a
j they are ordered by decreasing length. The next line contains an integer
m that is the number of queries (1 ≤
m ≤ 10
5).
j’th of the next
m lines contains an integer
c
j that is the coordinate of the point (1 ≤
c
j ≤ 10
9). The queries are ordered by non-decreasing
c
j.
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 |
Problem Author: Mikhail Rubinchik, idea by Nikita Pervukhin
To submit the solution for this problem go to the Problem set: 1987. Nested Segments
题意:
给你一些线段。然后得你一些点的坐标。问你找出包含该点的最短的一条线段。注意是标号而不是长度。。
思路:
开始以为长度结果看了半天。。。由于坐标的范围太大而线段的数目有限。所以要离散化。然后就是简单的线段树成段更新了。
详细见代码:
#include<algorithm>
#include<iostream>
#include<string.h>
#include<sstream>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100010;
int x[maxn<<2],y[maxn<<1],li[maxn],ri[maxn],len[maxn<<4],id[maxn<<4];
int ptr,cnt;
void btree(int L,int R,int k)
{
int ls,rs,mid;
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
len[k]=INF;//记录对应的最小长度
id[k]=-1;//对应的线段标号
if(L==R)
return ;
btree(L,mid,ls);
btree(mid+1,R,rs);
}
void pushdown(int k)
{
int ls,rs;
ls=k<<1;
rs=ls|1;
if(len[ls]>len[k])
{
id[ls]=id[k];
len[ls]=len[k];
}
if(len[rs]>len[k])
{
id[rs]=id[k];
len[rs]=len[k];
}
len[k]=INF;
id[k]=-1;
}
void update(int L,int R,int l,int r,int k,int d,int idd)
{
int ls,rs,mid;
if(l==L&&r==R)
{
if(len[k]>d)
{
len[k]=d;
id[k]=idd;
}
return;
}
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
if(len[k]!=INF)
pushdown(k);
if(l>mid)
update(mid+1,R,l,r,rs,d,idd);
else if(r<=mid)
update(L,mid,l,r,ls,d,idd);
else
{
update(L,mid,l,mid,ls,d,idd);
update(mid+1,R,mid+1,r,rs,d,idd);
}
}
int binf(int p)//二分查找离散后的标号
{
int mid,l,r;
l=1,r=ptr-1;
while(l<=r)
{
mid=(l+r)>>1;
if(x[mid]==p)
return mid;
else if(p>x[mid])
l=mid+1;
else
r=mid-1;
}
return -1;
}
int qu(int L,int R,int p,int k)
{
int ls,rs,mid;
if(L==R||len[k]!=INF)
return id[k];
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
if(p>mid)
return qu(mid+1,R,p,rs);
else
return qu(L,mid,p,ls);
}
int binp(int p)//如果p不是端点值的话需二分查找
{
int mid,l,r,ans=-1;
l=1,r=cnt-1;
while(l<=r)
{
mid=(l+r)>>1;
if(y[mid]==p)
return mid;
else if(p>y[mid])
{
l=mid+1;
ans=mid;
}
else
r=mid-1;
}
if(ans!=-1)
return binf(y[ans])+1;
return -1;
}
int main()
{
int i,l,r,n,m,p,ans,temp;
while(~scanf("%d",&n))
{
ptr=cnt=1;
for(i=1; i<=n; i++)
{
scanf("%d%d",&li[i],&ri[i]);
x[ptr++]=li[i];
x[ptr++]=ri[i];
}
sort(x,x+ptr);
for(i=1;i<ptr;i++)
y[cnt++]=x[i];
temp=ptr;
ptr=1;
for(i=1; i<temp; i++)//离散化去重点
if(x[i]!=x[i-1])
x[ptr++]=x[i];
for(i=ptr-1; i>1; i--)
if(x[i]-x[i-1]>1)//离散化加中点
x[ptr++]=x[i-1]+1;
sort(x,x+ptr);
btree(1,ptr,1);
for(i=1;i<=n;i++)
{
l=binf(li[i]);
r=binf(ri[i]);
update(1,ptr,l,r,1,ri[i]-li[i]+1,i);
}
scanf("%d",&m);
while(m--)
{
scanf("%d",&p);
if(p<x[1]||p>x[ptr-1])
ans=-1;
else
{
temp=binf(p);
if(temp==-1)
p=binp(p);
else
p=temp;
if(p==-1)
ans=-1;
else
ans=qu(1,ptr,p,1);
}
printf("%d\n",ans);
}
}
return 0;
}