【jzoj4882】【多段线性函数】

来源:互联网 发布:淘宝店标图片尺寸 编辑:程序博客网 时间:2024/06/05 06:36

题目大意

这里写图片描述

解题思路

考虑一个数在区间左边和右边才贡献,先把标记打在边界,然后像前缀和那样传递,然后离散化选的点一定在边界上,枚举选的点利用预处理的信息即可求出答案。

code

#include<set>#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define LL long long#define LD double#define max(a,b) ((a>b)?a:b)#define min(a,b) ((a>b)?b:a)#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)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;}
0 0