如果没有秒杀,就是经典的国王游戏问题,按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. 【译】第二篇 Integration Services:SSIS数据泵

    本篇文章是Integration Services系列的第二篇,详细内容请参考原文. 简介SSIS用于移动数据.数据流任务提供此功能.因为这个原因,当介绍SSIS时我喜欢从数据流任务开始.数据流任务的 ...

  2. P1879 [USACO06NOV]玉米田Corn Fields (状压dp入门)

    题目链接: https://www.luogu.org/problemnew/show/P1879 具体思路: 我们可以先把所有合法的情况枚举出来,然后对第一行判断有多少种情况满足,然后对于剩下的行数 ...

  3. Computer Vision Resources

    Computer Vision Resources Softwares Topic Resources References Feature Extraction SIFT [1] [Demo pro ...

  4. [转]closed-form solution (闭合解/解析解)和数值解的理解

    参考整理自:http://hi.baidu.com/cjb366/item/7290773b2d2eb9f2a9842873 closed-form solution :一般翻译为闭合解/解析解.这一 ...

  5. python 元组分组并排序

    # -*- coding: utf-8 -*- # @Time : 2018/8/31 14:32 # @Author : cxa # @File : glomtest.py # @Software: ...

  6. php 中更简洁的三元运算符 ?:

    PHP 三元运算符是对参数赋值时候的一个简洁的主要用法. 一个主要的用法: PHP 三元运算符能够让你在一行代码中描述判定代码, 从而替换掉类似以下的代码: <?php if (isset($v ...

  7. [ python ] 学习目录大纲

    简易博客[html+css]练习 MySQL 练习题及答案 MySQL视图.触发器.函数.存储过程 MySQL 操作总结 Day41 - 异步IO.协程 Day39/40 - 线程的操作 Day36/ ...

  8. mybatis 易百练习笔记

    1. session.commit()  增删改需要提交     session.close()    session需要关闭 2. insert  into t()   values()  不用写i ...

  9. SpringCloud Config Bus webhook 只能刷新config server 不能刷新config client

    在 https://github.com/spring-cloud/spring-cloud-bus/issues/124 中有提到 版本 SpringCloud:Greenwich.RC1 原因 由 ...

  10. 大家来探讨下,IRepository 应该怎么定义?

    ORM已EF为例子:我见的最多的是泛型的IRepository, public partial interface IRepository<T> where T : BaseEntity{ ...