https://vjudge.net/problem/CodeForces-1251Dhtml
您是一个大型企业的负责人。在您的企业当中共有n位员工为您工做,并且很是有趣的事是这个n是一个奇数(n不能被2整除)。node
您必须给你的员工分配工资。最初,您有s美圆,而第ii个员工应得的薪水应该是li∼ri之间的一个值。而不管怎么分配每一个人的工资,您必须使得全部分配的工资的中位数最大。ios
对于一个长度为奇数的序列,若是要找到他的中位数,就须要先对这个序列进行排序,以后找到中间位置的数字。举例来讲:c++
保证您有足够的钱来支付最低的工资,即l1+l2+⋯+ln≤s。spa
注意,您没必要把全部的钱都花在员工的开支上。.net
假设符合要求的中位数为x,首先,按右端点从小到大排序,ri的中位数便是x的上界;按左端点排序,获得x的下界为li的中位数。这个很好理解,画个数轴,基本就是那回事。。而后咱们在x的上下界里二分,check所花费用是否小于等于s便可。怎么check呢?考虑贪心,对于ri<x的数,咱们就取li,这样能够腾出更多的资金;对于li>x的数,咱们取li,也是为了腾出更多资金;对于li~ri穿插x的数,咱们先丢一块儿。经过刚才的判断咱们能够获得放到x左边和右边的个数,如今咱们遍历穿插的数,若是当前x左边的个数小于右边,那么这个数得用来放到左边,用最小的li便可;不然放到右边,用x的值便可。最后还剩一个数,那就是中位数x啦,因此判断tmp+x<=s便可。htm
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=200005; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) struct node { ll l,r; } g[N]; int n; ll s; bool cmp1(node a,node b) { return a.l<b.l; } bool cmp2(node a,node b) { return a.r<b.r; } node gg[N]; bool check(ll x) { ll tmp=0,l=0,r=0,cnt=0; for(int i=1; i<=n; i++) { if(g[i].l>x) tmp+=g[i].l,r++; else if(g[i].r<x) { tmp+=g[i].l,l++; } else { gg[cnt++]=g[i]; } } int i=0,j=cnt-1; while(i<j) { if(l<r) tmp+=gg[i].l,l++,i++; else tmp+=x,r++,j--; } // cout<<"gg"<<endl; return tmp+x<=s; } int main() { std::ios::sync_with_stdio(false); int t; cin>>t; while(t--) { cin>>n>>s; for(int i=1; i<=n; i++) { cin>>g[i].l>>g[i].r; } sort(g+1,g+1+n,cmp2); ll R=g[n/2+1].r; sort(g+1,g+1+n,cmp1); ll L=g[n/2+1].l; ll l=L,r=R,mid,ans=L; while(l<=r) { mid=(l+r)>>1; if(check(mid)) { l=mid+1; ans=mid; } else r=mid-1; } cout<<ans<<endl; } return 0; }