题目大意

解题思路
考虑一个数在区间左边和右边才贡献,先把标记打在边界,然后像前缀和那样传递,然后离散化选的点一定在边界上,枚举选的点利用预处理的信息即可求出答案。
code
using namespace std;
int const inf=1e9,maxn=1e5,mod1=1e9+7,mod2=998244353,size=29989;
int n,l[maxn+10],r[maxn+10],a[maxn*2+10],b[maxn*2+10],c[maxn*2+10],
lnum[maxn*2+10],rnum[maxn*2+10];
LL lsum[maxn*2+10],rsum[maxn*2+10];
int get(int x){
int l=1,r=a[0];
for(;l!=r;){
int m=(l+r)/2;
if(a[m]<x)l=m+1;
else r=m;
}
return b[l];
}
int main(){
freopen("linear.in","r",stdin);
freopen("linear.out","w",stdout);
scanf("%d",&n);
fo(i,1,n){
scanf("%d%d",&l[i],&r[i]);
a[++a[0]]=l[i];a[++a[0]]=r[i];
}
sort(a+1,a+a[0]+1);
b[1]=1;c[1]=a[1];fo(i,2,a[0]){b[i]=b[i-1]+(a[i]!=a[i-1]),c[b[i]]=a[i];}
fo(i,1,n){
l[i]=get(l[i]);rnum[l[i]]++;rsum[l[i]]+=c[l[i]];
r[i]=get(r[i]);lnum[r[i]]++;lsum[r[i]]+=c[r[i]];
}
fd(i,b[a[0]],1){
rnum[i]+=rnum[i+1];
rsum[i]+=rsum[i+1];
}
LL mi=1e16;int beg,end;
fo(i,1,b[a[0]]){
lnum[i]+=lnum[i-1];
lsum[i]+=lsum[i-1];
if(1ll*c[i]*lnum[i]-lsum[i]+rsum[i]-1ll*c[i]*rnum[i]<mi){
mi=1ll*c[i]*lnum[i]-lsum[i]+rsum[i]-1ll*c[i]*rnum[i];
beg=end=c[i];
}else if(1ll*c[i]*lnum[i]-lsum[i]+rsum[i]-1ll*c[i]*rnum[i]==mi)end=c[i];
}
printf("%d %d",beg,end);
return 0;
}