如果没有秒杀,就是经典的国王游戏问题,按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. OpenCV 用二进制位表示 type & channels 的方式

    OpenCV 的类型与通道的表示方法. 参考文件 https://github.com/opencv/opencv/blob/05b15943d6a42c99e5f921b7dbaa8323f3c04 ...

  2. SQL Server 问题之 排序规则(collation)冲突

    一.写在前面 最近公司进行开发环境升级,数据库也准备了一个新的服务器,一切准备好后开始数据迁移,采取的方式为对现有Database(现有服务器Windows Server 2003 + SQL Ser ...

  3. Servlet笔记2--模拟Servlet本质、第一个Servlet程序、将响应结果输出到浏览器中

    以下代码均非IDE开发,所以都不规范,仅供参考 模拟Servlet本质: 模拟Servlet接口: /* SUN公司制定的JavaEE规范:Servlet规范 Servlet接口是Servlet规范中 ...

  4. 【FCS NOI2018】福建省冬摸鱼笔记 day1

    省冬的第一天. 带了本子,笔,一本<算法导论>就去了.惊讶于为什么同学不带本子记笔记. 他们说:“都学过了.”,果然这才是巨神吧. 第一天:数论,讲师:zzx 前几页的课件挺水,瞎记了点笔 ...

  5. 移动端测试===PROC系列之---/proc/pid/stat 如何准确取cpu的值【转】

         /proc/ /stat 包含了所有CPU活跃的信息,该文件中的所有值都是从系统启动开始累计到当前时刻. [root@localhost ~]# cat /proc/6873/stat 68 ...

  6. 金蝶K3WISE常用数据表

    K3Wise 14.2 清空密码update t_User set FSID=') F ", ,P T #8 *P!D &D 80!N &@ <0 C '+''''+' ...

  7. spring boot 测试用例

    junit 是一个面向于研发人员使用的轻量的测试模块,适合做单元测试.而testng百度后发现更强大,可以做功能测试,但对于我这种RD,貌似junit足沟了呢! java Mock PowerMock ...

  8. Gradle设置代理

    在本地仓库路径下(如果没有修改的话默认C:\Users\用户名\.gradle),或者项目下,新建一个文件gradle.properties systemProp.http.proxyHost=网址 ...

  9. java基础81 jsp的内置对象(网页知识)

    1.什么是内置对象? 在jsp开发中,会频繁使用到一些对象,如:HttpSession,ServletContext,HttpServletRequest.      如果每次使用这些对象时,都要去创 ...

  10. arp命令 清arp表

    平常删除arp都用arp-d.大量存在的时候 arp -n|awk '/^[1-9]/ {print arp -d $1}' | sh 清除所有arp表,以前用这个来清arp表貌会清空,没注意到存在i ...