如果没有秒杀,就是经典的国王游戏问题,按t/a从小到大排序即可。

考虑删除两个数i<j能给答案减少的贡献:S[i]*T[i]+P[i-1]*A[i]-A[i]+S[j]*T[j]+P[j-1]*A[j]-A[j]-T[i]*A[j]

其中P为T=(D-1)/ATK+1的前缀和,S为A的后缀和。

我们设bi=S[i]*T[i]+P[i-1]*A[i]-A[i],考虑当i固定时,j可能取什么值。

解法一:CDQ分治

不难发现,当i<j<k时k比j优的充要条件是b[k]-T[i]*A[k]>b[j]-T[i]*A[j],即T[i]<(b[k]-b[j])/(A[k]-A[j])。

不难看出斜率优化的模型,最后要最大化的是b[k]-T[i]*A[k]即所有点(A[k],b[k])以-T[i]的斜率投影到y轴上的最高点,于是答案一定在上凸壳上。

注意到这里点的横坐标A和询问斜率T均不单调,需要CDQ分治。

每次分治左半边按T排序,右半边按A排序并将凸包建好,然后左端点从前往后扫即可。

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
int n,m,q[N];
ll A,B,ans,tot,c[N];
struct P{ int x,y; ll z; }a[N],b[N]; bool cmp(const P &a,const P &b){ return a.x*b.y>b.x*a.y; }
bool cmp2(const P &a,const P &b){ return a.y>b.y; }
bool cmp3(const P &a,const P &b){ return a.x<b.x; }
ll calc(int x,int y){ return tot-a[x].z-a[y].z+a[y].x*a[x].y; }
double sl(int x,int y){ return (double)(a[y].z-a[x].z)/(a[y].x-a[x].x); } void solve(int l,int r){
if (l>=r) return;
int mid=(l+r)>>;
solve(l,mid); solve(mid+,r);
sort(a+l,a+mid+,cmp2); sort(a+mid+,a+r+,cmp3);
int st=,ed=;
rep(i,mid+,r){
while (st<ed && sl(q[ed-],q[ed])<sl(q[ed],i)) ed--;
q[++ed]=i;
}
rep(i,l,mid){
while (st<ed && sl(q[st],q[st+])>a[i].y) st++;
ans=min(ans,calc(i,q[st]));
}
} int main(){
freopen("bzoj4700.in","r",stdin);
freopen("bzoj4700.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,n) scanf("%d%d",&a[i].x,&a[i].y),A+=a[i].x,a[i].y=(a[i].y-)/m+;
sort(a+,a+n+,cmp);
rep(i,,n){
A-=a[i].x; B+=a[i].y;
a[i].z=a[i].x*(B-)+A*(a[i].y);
tot+=a[i].x*(B-);
}
ans=tot; solve(,n); printf("%lld\n",ans);
return ;
}

解法二:李超树

不难发现,i固定时,j对答案减小的贡献是b[j]-T[i]*A[j],这个式子可以理解为直线y=-A[j]*x+b[j]在T[i]处的总坐标。

问题转化为,i从大到小枚举,需要支持插入一条直线与在线查询某个横坐标上所有直线总坐标最大值。

动态维护凸包问题,显然用李超树。

 #include<cstdio>
#include<algorithm>
#define ls (x<<1)
#define rs (ls|1)
#define lson ls,L,mid
#define rson rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
int n,m,v[N<<];
ll tot,ans,res,L[N],S[N],k[N],b[N];
struct P{ int a,t; }p[N];
bool operator <(const P &a,const P &b){ return a.a*b.t>b.a*a.t; }
bool pd(int x,int y,int p){ return k[x]*p+b[x]>k[y]*p+b[y]; }
ll calc(int x,int p){ return k[x]*p+b[x]; } void ins(int x,int L,int R,int p){
if (L==R){ if (pd(p,v[x],L)) v[x]=p; return; }
int mid=(L+R)>>;
if (k[p]>k[v[x]]){
if (pd(p,v[x],mid)) ins(lson,v[x]),v[x]=p; else ins(rson,p);
}else{
if (pd(p,v[x],mid)) ins(rson,v[x]),v[x]=p; else ins(lson,p);
}
} void que(int x,int L,int R,int k){
res=max(res,calc(v[x],k));
if (L==R) return;
int mid=(L+R)>>;
if (k<=mid) que(lson,k); else que(rson,k);
} int main(){
freopen("bzoj4700.in","r",stdin);
freopen("bzoj4700.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,n) scanf("%d%d",&p[i].a,&p[i].t),p[i].t=(p[i].t-)/m+;
sort(p+,p+n+);
rep(i,,n) L[i]=L[i-]+p[i].t;
for (int i=n; i; i--) S[i]=S[i+]+p[i].a;
rep(i,,n) k[i]=-p[i].a,b[i]=S[i]*p[i].t+L[i-]*p[i].a-p[i].a,tot+=p[i].t*S[i]-p[i].a;
ins(,,n,n);
for (int i=n-; i; i--)
res=,que(,,n,p[i].t),ans=max(ans,b[i]+res),ins(,,n,i);
printf("%lld\n",tot-ans);
return ;
}

[BZOJ4700]适者(CDQ分治+DP/李超线段树)的更多相关文章

  1. Codechef TSUM2 Sum on Tree 点分治、李超线段树

    传送门 点分治模板题都不会迟早要完 发现这道题需要统计所有路径的信息,考虑点分治统计路径信息. 点分治之后,因为路径是有向的,所以对于每一条路径都有向上和向下的两种.那么如果一条向上的路径,点数为\( ...

  2. cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)

    题意: 给出n个三元组 e[i]=(si,ti,wi) 第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件: 1.j<i 2.tj<ti 3.sj<si 4.不存在j< ...

  3. Codeforces 1175G Yet Another Partiton Problem [DP,李超线段树]

    Codeforces 思路 首先吐槽一句:partiton是个什么东西?我好像在百度翻译里面搜不到呀qwq 发现不了什么性质,那就直接上DP吧.注意到DP可以分层,所以设\(dp_i\)表示当前层,分 ...

  4. [CF1303G] Sum of Prefix Sums - 点分治,李超线段树

    给定一棵 \(n\) 个点的带点权的树,求树上的路径 \(x_1,...,x_k\) ,最大化 \(\sum_{i=1}^k ia_{x_i}\) Solution 树上路径问题可用点分治. 考虑如何 ...

  5. Codeforces 1303G - Sum of Prefix Sums(李超线段树+点分治)

    Codeforces 题面传送门 & 洛谷题面传送门 个人感觉这题称不上毒瘤. 首先看到选一条路径之类的字眼可以轻松想到点分治,也就是我们每次取原树的重心 \(r\) 并将路径分为经过重心和不 ...

  6. luogu4849 寻找宝藏 (cdq分治+dp)

    设f[i]是已经走到i号点的值. 先要给第四维离散化.然后去重 第一维排序,第二维cdq分治,第三维cdq分治,第四维树状数组,找到满足j(x,y,z,w)<=i(x,y,z,w)的j,给i统计 ...

  7. Codeforces 1175G - Yet Another Partiton Problem(李超线段树)

    Codeforces 题面传送门 & 洛谷题面传送门 这是一道李超线段树的毒瘤题. 首先我们可以想到一个非常 trivial 的 DP:\(dp_{i,j}\)​ 表示前 \(i\)​ 个数划 ...

  8. Codeforces Round #463 F. Escape Through Leaf (李超线段树合并)

    听说正解是啥 set启发式合并+维护凸包+二分 根本不会啊 , 只会 李超线段树合并 啦 ... 题意 给你一颗有 \(n\) 个点的树 , 每个节点有两个权值 \(a_i, b_i\) . 从 \( ...

  9. 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交

    4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][ ...

随机推荐

  1. java数字转字符串前面自动补0或者其他数字

    /**  * Java里数字转字符串前面自动补0的实现.  *  * @author  xiaomo *  */  public class TestStringFormat {    public ...

  2. 【codeforces】【比赛题解】#868 CF Round #438 (Div.1+Div.2)

    这次是Div.1+Div.2,所以有7题. 因为时间较早,而且正好赶上训练,所以机房开黑做. 然而我们都只做了3题.:(. 链接. [A]声控解锁 题意: Arkady的宠物狗Mu-mu有一只手机.它 ...

  3. Cloud Lab: 泰晓实验云台【转】

    转自:http://tinylab.org/cloud-lab/ 可快速构建的计算机课程在线实验平台 由 Wu Zhangjin 创建于 2017/10/06 评论 打赏 项目描述 泰晓实验云台 项目 ...

  4. GDB调试基础

    GDB调试基础 https://lesca.me/archives/gdb-basic-knowledge.html GDB笔记(二):条件断点.命令列表.监视点 https://lesca.me/a ...

  5. static, const 和 static const 变量的初始化问题

    const 常量的在超出其作用域的时候会被释放,但是 static 静态变量在其作用域之外并没有释放,只是不能访问. static 修饰的是静态变量,静态函数.对于类来说,静态成员和静态函数是属于整个 ...

  6. linux系统时钟和硬件时钟不一致

    在做DB2 集群复制的时候要求两台主机时间相互一致. 但是在一台主机上系统时间和硬件时间相差12个小时左右:手动同步后,重启后又相差12个小时左右. 为什么会是这样的,先介绍下系统时钟和硬件时钟的区别 ...

  7. python 写入execl记录

    记录代码中关于写execl的操作 # 创建execl workbook = xlwt.Workbook(encoding='utf8') # 创建样式实例 style = xlwt.XFStyle() ...

  8. laravel 中provider的理解和使用

    https://segmentfault.com/q/1010000004640866

  9. python网络编程--进程池

    一:进程池 进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程, 如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止. 进程池中有两个方法: apply a ...

  10. 国内能用的NTP服务器及和标准源的偏差值

    中国境内可以使用的NTP服务器的IP地址,和泰福特服务器的时间偏差值,泰福特时钟服务器实时连接天线,测试前已经连接天线超过72小时 time-a.nist.gov 129.6.15.28 NIST, ...