• BZOJ4700: 适者


    先排序,枚举删一个点,在前面找出最优的另一个点,容易推出斜率方程,平衡树维护凸包。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=3e5+5;
    typedef struct node*ptr;
    struct node{
    	ptr i,j,s,t;
    	ll w,x,y;
    	node(){w=rand();}
    }*b,e[N];
    void zag(ptr&o){ptr s=o->j;o->j=s->i,s->i=o,o=s;}
    void zig(ptr&o){ptr s=o->i;o->i=s->j,s->j=o,o=s;}
    void ins(ptr j,ptr&o=b){
    	if(!o)o=j,o->s?o->s->t=o:0,o->t?o->t->s=o:0;
    	else if(j->x>o->x)
    		{ins(j,o->j);if(o->j->w>o->w)zag(o);}
    	else if(o->x>j->x)
    		{ins(j,o->i);if(o->i->w>o->w)zig(o);}
    }
    void del(ptr j,ptr&o=b){
    	if(j->x>o->x)del(j,o->j);
    	else if(o->x>j->x)del(j,o->i);
    	else if(!o->i)o=o->j;
    	else if(!o->j)o=o->i;
    	else if(o->i->w>o->j->w)zig(o),del(j,o->j);
    	else zag(o),del(j,o->i);
    }
    ptr pre(ll x,ptr o=b){
    	ptr s=0;
    	while(o)x>=o->x?s=o,o=o->j:o=o->i;
    	return s;
    }
    ptr suc(ll x,ptr o=b){
    	ptr s=0;
    	while(o)o->x>=x?s=o,o=o->i:o=o->j;
    	return s;
    }
    ll cal(ptr o,ptr s,ptr t){
    	ll x1=o->x-s->x,y1=o->y-s->y;
    	ll x2=t->x-s->x,y2=t->y-s->y;
    	return x1*y2-x2*y1;
    }
    void upd(ptr o){
    	if(ptr&s=o->s=pre(o->x))
    		while(s->s&&cal(o,s->s,s)<=0)
    			del(s),s=pre(o->x);
    	if(ptr&t=o->t=suc(o->x))
    		while(t->t&&cal(o,t,t->t)<=0)
    			del(t),t=suc(o->x);
    	if(!o->s||!o->t)ins(o);
    	else
    		if(cal(o->s,o,o->t)>0)ins(o);
    }
    ll slo(ptr s,ptr t){return(s->y-t->y)/(s->x-t->x);}
    ptr sol(ll k,ptr o=b){
    	if(o->s&&k>slo(o->s,o))return sol(k,o->i);
    	if(o->t&&slo(o,o->t)>k)return sol(k,o->j);
    	return o;
    }
    struct foo{int s,t;}c[N];
    bool operator<(foo s,foo t){return s.t*t.s<t.t*s.s;}
    int n,m,d;
    ll k,q,s[N],r[N];
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d%d",&c[i].s,&d);
    		c[i].t=(d+m-1)/m;
    	}
    	sort(c+1,c+n+1);
    	for(int i=1;i<=n;++i)
    		s[i]=s[i-1]+c[i].t;
    	for(int i=n;i;--i){
    		k+=(s[i]-1)*c[i].s;
    		r[i-1]=r[i]+c[i].s;
    		e[i].x=c[i].t;
    		e[i].y=(s[i]-1)*c[i].s+c[i].t*r[i];
    	}
    	upd(e+1);
    	for(int i=2;i<=n;++i){
    		ptr j=sol(c[i].s);
    		q=max(q,e[i].y+j->y-j->x*c[i].s);
    		upd(e+i);
    	}
    	printf("%lld
    ",k-q);
    }
    
  • 相关阅读:
    c#格林治时间实现
    K3WISE常用表
    读取单元格数据
    水晶报表使用方法
    vs2010下使用sqlite
    C#执行EXE程序
    SQLLITE HELPER
    SQL LITE安装
    C#多线程
    VS2012 快捷键
  • 原文地址:https://www.cnblogs.com/f321dd/p/6124097.html
Copyright © 2020-2023  润新知