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)/~