正题

题目链接:https://www.ybtoj.com.cn/problem/463


题目大意

给出长度为nnn的序列A,BA,BA,B。要求划分成若干段满足

  1. 对于任何i<ji<ji<j,若iii和jjj不是同一段的,要求满足Bi>AjB_i>A_jBi​>Aj​
  2. 每一段AiA_iAi​的最大值的和不能超过mmm

要求最小化每一段BiB_iBi​和的最大值。

n∈[1,105],Ai,Bi∈[1,109],m∈[1,1012]n\in[1,10^5],A_i,B_i\in[1,10^9],m\in[1,10^{12}]n∈[1,105],Ai​,Bi​∈[1,109],m∈[1,1012]


解题思路

最大值最小化很显然直接二分,然后变为求每一段AiA_iAi​最大值的和的最小值。

第一个条件相当于限制了什么位置能够作为划分段的末尾,求一个前缀min{bi}min\{b_i\}min{bi​}和一个后缀max{ai}max\{a_i\}max{ai​}能够快速求出这些位置。

然后考虑dpdpdp,转移方程就是
fi=min{fj+max{ak}(k∈(j,i])}f_i=min\{f_j+max\{a_k\}(\ k\in(j,i]\ )\}fi​=min{fj​+max{ak​}( k∈(j,i] )}

二分的条件限制了jjj的范围,加个指针就好了

这个东西好像很难搞,但是注意到vj=max{ak}v_j=max\{a_k\}vj​=max{ak​}这一部分是递减的,并且每次会让所有viv_ivi​的一起和一个一起取maxmaxmax。

因为是递减的,所以每次加入一个新的就相当于修改一段后缀的viv_ivi​,然后求一个区间的最大fi+vif_i+v_ifi​+vi​了。

可以线段树维护,每个节点维护该区间最大的fi+vif_i+v_ifi​+vi​和最大的fif_ifi​。区间推平viv_ivi​的时候就可以拿最大的fif_ifi​来更新fi+vif_i+v_ifi​+vi​

时间复杂度O(nlog⁡nlog⁡∑bi)O(n\log n\log\sum b_i)O(nlognlog∑bi​)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10,inf=1e9+7;
ll n,m,a[N],b[N],pre[N],suf[N],last[N];
ll lg[N],st[N][17],v[N<<2],w[N<<2],lazy[N<<2];
void Downdata(ll x){if(!lazy[x])return;lazy[x*2]=lazy[x*2+1]=lazy[x];w[x*2]=v[x*2]+lazy[x];w[x*2+1]=v[x*2+1]+lazy[x];lazy[x]=0;return;
}
void Changew(ll x,ll L,ll R,ll l,ll r,ll val){if(l>r)return;if(L==l&&R==r){w[x]=v[x]+val;lazy[x]=val;return;}ll mid=(L+R)>>1;Downdata(x);if(r<=mid)Changew(x*2,L,mid,l,r,val);else if(l>mid)Changew(x*2+1,mid+1,R,l,r,val);else Changew(x*2,L,mid,l,mid,val),Changew(x*2+1,mid+1,R,mid+1,r,val);w[x]=min(w[x*2],w[x*2+1]);
}
void Changev(ll x,ll l,ll r,ll pos,ll val){if(l==r){v[x]=val;w[x]=v[x]+lazy[x];return;}ll mid=(l+r)>>1;Downdata(x);if(pos<=mid)Changev(x*2,l,mid,pos,val);else Changev(x*2+1,mid+1,r,pos,val);w[x]=min(w[x*2],w[x*2+1]);v[x]=min(v[x*2],v[x*2+1]);return;
}
ll Ask(ll x,ll L,ll R,ll l,ll r){if(L==l&&R==r)return w[x];ll mid=(L+R)>>1;Downdata(x);if(r<=mid)return Ask(x*2,L,mid,l,r);if(l>mid)return Ask(x*2+1,mid+1,R,l,r);return min(Ask(x*2,L,mid,l,mid),Ask(x*2+1,mid+1,R,mid+1,r));
}
ll RMQ(ll l,ll r){ll z=lg[r-l+1];return max(st[l][z],st[r-(1<<z)+1][z]);
}
bool check(ll x){memset(v,0x3f,sizeof(v));memset(w,0x3f,sizeof(w));memset(lazy,0,sizeof(lazy));ll sum=0,l=0,tmp=v[0];Changev(1,0,n,0,0);for(ll i=1;i<=n;i++){sum+=b[i];while(sum>x)l++,sum-=b[l];Changew(1,0,n,last[i],i-1,a[i]);if(pre[i]<=suf[i+1])continue;tmp=Ask(1,0,n,l,i);Changev(1,0,n,i,tmp);}return (tmp<=m);
}
signed main()
{freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);scanf("%lld%lld",&n,&m);ll l=1,r=0;pre[0]=inf;for(ll i=1;i<=n;i++)scanf("%lld%lld",&a[i],&b[i]),r+=b[i],l=max(l,b[i]),st[i][0]=a[i];for(ll i=2;i<=n;i++)lg[i]=lg[i>>1]+1;for(ll j=1;(1<<j)<=n;j++)for(ll i=1;i+(1<<j)-1<=n;i++)st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);for(ll i=1;i<=n;i++){ll l=1,r=i-1;while(l<=r){ll mid=(l+r)>>1;if(RMQ(mid,i)>a[i])l=mid+1;else r=mid-1;}last[i]=r;}for(ll i=1;i<=n;i++)pre[i]=min(pre[i-1],b[i]);for(ll i=n;i>=1;i--)suf[i]=max(suf[i+1],a[i]);while(l<=r){ll mid=(l+r)>>1;if(check(mid))r=mid-1;else l=mid+1;}check(l+1);printf("%lld\n",l);
}

YbtOJ#463-序列划分【二分答案,线段树,dp】相关推荐

  1. 【TJOI2016】【bzoj4552】排序(二分答案+线段树01排序)

    problem 给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序 排序分为两种 1:(0,l,r)表示将区间[l,r]的数字升序排序 2:(1,l,r)表示将区间[l,r]的数字降序排序 ...

  2. P1295 [TJOI2011]书架(线段树dp)

    P1295 [TJOI2011]书架(线段树dp) 我好菜 先考虑普通dp: d p i = m i n ( d p j + m a x ( h j + 1 , h j + 2 - , h i ) ) ...

  3. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  4. YbtOJ#763-攻城略池【线段树合并】

    正题 题目链接:http://www.ybtoj.com.cn/problem/763 题目大意 给出nnn个点的一棵树,每个di=0d_i=0di​=0的点每秒会产生一个士兵往根节点走,走到一个节点 ...

  5. CodeForces - 487B Strip(线段树+dp+二分)

    题目链接:点击查看 题目大意:给出一个长度为 n 的序列,现在要求分成尽可能少的子段,且每个子段需要满足: 最大值与最小值的差值小于等于 s 子段长度大于等于 l 题目分析:dp[ i ] 代表的是前 ...

  6. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  7. 猜数(二分、线段树)

    题目描述 对于一个长度为n的数列给出m个描述 每一个描述给出一个区间[a,b]的最小值的x 求从第几个描述开始矛盾 解析 本题关键是一个关于矛盾的充要条件: 如果存在一个最小值x,其所在的区间的交集( ...

  8. loj6169 相似序列(可持久化线段树)

    题目: https://loj.ac/problem/6169 分析: 如果是要求两段序列全等的话,有一个套路: 对于{a1,a2,a3} {a4,a5,a6} 设一个素数p,那么如果p^a1+p^a ...

  9. szu 寒训个人复习第一天 线段树入门单点修改,区间修改,以及线段树的扩展运用[线段树+dp][区间最大公约数]

    寒讯内容有点过多(其实是我太菜了)水一波怕忘了(人老了)**什么是线段树** 线段树是本蒟蒻感觉用处特别大的算法 那么线段树上面的节点表示什么意思呢? 线段树,上面的节点表示一个区间,父亲节点表示的区 ...

最新文章

  1. 27年安全技术老兵无奈“一摔成名”,谭晓生自述一年创业进展
  2. 3.11 TensorFlow-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  3. ultraedit java_UltraEdit配置java环境
  4. 数据中心水冷系统备品备件管理新思路
  5. 一网打尽,最全面的跨域解决方案来了!
  6. 常用Function Module
  7. ORACLE SGA问题分析
  8. springboot创建parent_理解spring-boot-starter-parent
  9. python实现逐步回归分析_Python实现逐步回归(stepwise regression)
  10. WCF从理论到实践(5):Binding细解(转)
  11. 虚拟机的管理(libvirtd)、移植和快照
  12. 十年北漂,一个软件“攻城狮”到职业养鸡人的心路历程
  13. 丰富的else语句及简洁的with语句 - 零基础入门学习Python034
  14. Context 使用不当造成内存泄露
  15. 马尔可夫链与隐马尔可夫模型
  16. 部署企业级项目管理系统(蝉道)
  17. 单片机 TDA8023 读 ic 卡 smrat card sync_card
  18. JT/T-1078流媒体服务优化升级
  19. 分辨率、帧率、码率之间的关系
  20. zipkin+elk微服务日志收集分析系统

热门文章

  1. Java将mysql输出csv_使用Java将大量数据从数据库导出到.csv时出...
  2. 2021年度最全面JVM虚拟机,类加载过程与类加载器
  3. html盒模型向上浮动,HTML5盒模型、浮动和定位
  4. java中如何运行小程序_一起学java(一)——运行第一个小程序
  5. yaml for java_细数Java项目中用过的配置文件(YAML篇)
  6. 查看服务器物理内存大小,如何看服务器的物理内存大小
  7. java context.write_Channel.write() 和 ChannelHandlerContext.write() 的区别
  8. mysql表空间权限_MySQL InnoDB表空间加密示例详解
  9. php代码里加图片,php如何添加图片
  10. leetcode279. 完全平方数