Welcome Party(线段树+二分)

Problem Description
The annual welcome party of the Department of Computer Science and Technology is coming soon! Many students have been applying to show up at the welcome party, and every one of them can choose to sing a song or play crosstalk. This troubles the chief director a lot: how to arrange the program list, such that every student can have a chance to show up on the stage, and the satisfactory value of audiences is maximized?

To cope with this problem, the director proposes a model. In this model, every student has two attributes: the singing ability and crosstalking ability. The satisfactory value of audiences to singings is the maximum singing ability among all students that choose to sing a song; similarly, the satisfactory value to crosstalks is the maximum crosstalking ability among all students that choose play crosstalk. The strange thing is, the overall satisfactory value to the whole party is negatively related to the absolute difference between the satisfactory values to singings and crosstalks. The problem is, what is the minimum possible absolute difference between the satisfactory values of the two types of programs?

Note that:

  • every student should choose exactly one type of programs to play;
  • at least one student should sing a song, and at least one student should play crosstalk.

Input
The first line of input consists of a single integer T (1≤T≤70), the number of test cases.

Each test case starts with a line of a single integer n (2≤n≤100000), denoting the number of students applying to show up on the stage. Then follow n lines, each containing two integers x and y (0≤x,y≤1018), denoting the singing ability and crosstalking ability of a student.

It is guaranteed that the sum of n over all test cases never exceeds 1000000.

Output
For each test case, output a single integer, denoting the minimum possible absolute difference between the satisfactory values of the two types of programs.

Sample Input
2
5
27 46
89 13
55 8
71 86
22 35
3
3 5
4 7
6 2

Sample Output
3
1
题意:每个人有两个特性,一个是说相声,一个是唱歌。n个人要被分成两个组(不一定平均分),一组说相声,一组唱歌。问这两组各自特性的最大值差值的绝对值最少是多少。
思路:像这种两个特性的,大多是按着一个排完序之后,去处理那一个。
我们按着相声能力由大到小排好序。去遍历1~ n。处理到第i个的时候,在1~ i之间第i个人的相声能力一定是最大的。我们把i+1到n的唱歌能力最大值找出来。。线段树求区间最大值max。但是只求出i+1~n的唱歌最大值并不一定就是最终的答案。因为在1 ~ i-1之间有可能会有比max更符合的值。那么什么时候才会有这种情况呢。假如max大于当前相声之ti,我们找到1 ~ i-1的更符合值是smax,如果smax<max,那么如果这两个在一个组里就不符合情况了,如果smax>max,那么max与ti的差值绝对值一定小于smax与ti的差值绝对值,这样无论如何就是max最符合了。假如max小于等于当前相声值ti,我们在1 ~i-1之间找到接近ti的两个值,这三个值一起去更新最后的答案ans。i+1 ~ n用线段树去找最大值,1 ~ i-1 用set去二分查找。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=1e5+100;
struct node{
	int l;
	int r;
	ll _max;
}p[maxx<<2];
struct Node{
	ll x;
	ll y;
	bool operator <(const Node &a)const{
		return a.x>x;
	}
}t[maxx];
int n;

void pushup(int cur)
{
	p[cur]._max=max(p[cur<<1]._max,p[cur<<1|1]._max);
}
inline void build(int l,int r,int cur)
{
	p[cur].l=l;
	p[cur].r=r;
	if(l==r)
	{
		p[cur]._max=t[l].y;
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,cur<<1);
	build(mid+1,r,cur<<1|1);
	pushup(cur);
}
inline ll query(int l,int r,int cur)
{
	int L=p[cur].l;
	int R=p[cur].r;
	if(l<=L&&R<=r) return p[cur]._max;
	int mid=L+R>>1;
	if(r<=mid) return query(l,r,cur<<1);
	else if(l>mid) return query(l,r,cur<<1|1);
	else return max(query(l,mid,cur<<1),query(mid+1,r,cur<<1|1));
}

int main()
{
	int tt;
	scanf("%d",&tt);
	while(tt--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%lld%lld",&t[i].x,&t[i].y);
		sort(t+1,t+1+n);
		build(1,n,1);
		ll ans=1e18;
		ll maxn;
		set<ll> ss;
		for(int i=1;i<n;i++)
		{
			maxn=query(i+1,n,1);
			if(maxn>=t[i].x) ans=min(ans,maxn-t[i].x);
			else 
			{
				set<ll> ::iterator q=ss.lower_bound(t[i].x);
				if(q!=ss.end()) ans=min(ans,*q-t[i].x);
				if(q!=ss.begin()) 
				{
					q--;
					ans=min(ans,abs(t[i].x-*q));
				}
				ans=min(ans,t[i].x-maxn);
			}
			ss.insert(t[i].y);
		}
		set<ll>::iterator q=ss.upper_bound(t[n].x);
		if(q!=ss.end())ans=min(ans,abs(*q-t[n].x));
		if(q!=ss.begin())
		{
			q--;
			ans=min(ans,abs(t[n].x-*q));
		}
		printf("%lld\n",ans);
	}
}

努力加油a啊,(o)/~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值