cf#ECR10-D. Nested Segments-树状数组+二分

http://codeforces.com/contest/652/problem/D


题意,给n个区间(端点保证不重复)

输出每个区间包含了多少个区间


先存起所有区间的左右端点,并依次对应编号


然后把左右端点 分别从小到大排序

并开一个树状数组,每个点对应着Yi,初始化值全为1

从小到大遍历左端点,

对于X1,找到其原始编号id,然后再找出对应的Y

然后在排序后的Y数组里 二分找到 Y的位置,那么 当前id的左端点是最左的,所有区间的左端点都在X1的后面,必然 当前区间可以把Y左边的所有区间都包含。  

【因为当前区间左端点最左,所以不会还有区间能包含它,因此把点Y在树状数组里挖掉】

求答案的话 就是在树状数组的1到Y-1 里面的节点个数,然后把Y这个节点挖掉,继续遍历左端点


每次求树状数组里1到Y-1的和,然后把 Y挖掉 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001; 
int ll[2*100005];
int rr[2*100005]; 
int sort_r[2*100005]; 
int min(int a,int b)
{return a<b?a:b;}

int tree[2*100005];
int n;
   int lowbit(int x)
{
	return x&-x;
}
void add(int x,int value)
{
	for (int i=x;i<=n;i=i+lowbit(i))
	{
		tree[i]+=value;
	}
}
int get(int x)
{
	int sum=0;
	for (int i=x;i;i-=lowbit(i))
	{
		sum+=tree[i];
	}
	return sum;
}
 struct node
 {
	 int x,y,id;
 };
 node tm[2*100005];
bool cmp(node a,node b)
{return a.x<b.x;}
int ans[2*100005];
 int main() 
{
	int i;
	cin>>n;
	for (i=1;i<=n;i++)
	{
		scanf("%d%d",&tm[i].x,&tm[i].y);
		ll[i]=tm[i].x;
		rr[i]=tm[i].y;
		sort_r[i]=rr[i];
		tm[i].id=i;
		add(i,1);
	}
	sort(tm+1,tm+1+n,cmp);
	sort(sort_r+1,sort_r+1+n);
	for (i=1;i<=n;i++)
	{  
		int id=tm[i].id;
		int yy=rr[id];
		int it=lower_bound(sort_r+1,sort_r+1+n,yy)-sort_r;
		int res=0;
		if (it==1) res=0;
		else res=get(it-1);
	ans[id]=res;
		add(it,-1);
	}
	
	for(i=1;i<=n;i++)
	{
		printf("%d\n",ans[i]);
	} 
	
	return 0;
	
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值