URAL1987. Nested Segments 线段树

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 ≤ 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. All segments are distinct. 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




题意:
有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;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值