[atARC117F]Gateau
假设序列bi为最终第i片上的草莓数,即需要满足:∀0≤i<2n,ai≤∑n−1j=0b(i+j)mod 2n
要求最小化∑2n−1i=0bi,显然增大bi一定仍满足条件,即具备单调性,二分并判断其是否可以为X
为了避免取模,将条件分为0≤i<n以及n≤i<2n两部分,分别可以写作:
1.∀0≤i<n,ai≤∑n−1j=0bi+j
2.∀n≤i<2n,ai≤∑2n−1j=ibj+∑i−n−1j=0bj,考虑后者中不被计算的是一个连续区间,可以用X减去这一段,即X−∑i−1j=i−n−1bj,移项后即∑i−1j=i−nbj≤X−ai
两部分分别限制了上下限,即条件也可以写作:∀0≤i<n,ai≤∑n−1j=0bi+j≤X−ai+n
对其求前缀和,令Si=∑i−1j=0bj,即要求ai≤Si+n−Si≤X−ai+n
另一方面,根据bi≥0,还要求Si≤Si+1(特别的,要求S0=0以及S2n−1≤X)
同时,上面这两个条件也是充分条件,问题即判断是否存在满足上述条件的Si
将之变形,最终所有条件都可以写作Si+x≤Sj,即差分约束的形式
更具体的来说,建有向边(i,j,x)并从0开始求最长路,令di为到i的最长路,即满足此条件
另外,有正环或最终d2n−1>X即无解(这里最长路才是S2n−1的最小值)
由于有正权边(求最长路),只能使用spfa,以及最外层的二分,复杂度为o(n2logA),且会被卡
事实上,由于这张图的特殊性,有如下做法:
如果将(n−1,n,0)这条边删去,将整张图看作上下两行,分别为[0,n)和[n,2n),图的结构即比较简单,仅包含上下两行对应点之的有环,以及两行向后的边
此时将两个对应点的最长路一起算,即没有了后效性,可以o(n)求出
(特别的,若ai+ai+n>X即存在两个对应点之间的正环,即无解)
加入这条边后,在没有正环的情况下,先忽略这条边求出最长路,再加入这条边后用Sn−1更新Sn并重复一次求最长路(仍然忽略这条边),若Sn−1发生变化必然存在正环,否则即求出了最长路
(另外更新Sn后,还需要判断是否满足Sn≤X−an)
这一做法复杂度o(nlogA),可以通过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define ll long long 5 int E,n,a[N]; 6 ll d[N]; 7 void calc(ll k){ 8 for(int i=1;i<n;i++){ 9 d[i]=max(d[i-1],d[i+n-1]+a[i+n]-k); 10 d[i+n]=max(d[i+n-1],d[i-1]+a[i]); 11 } 12 } 13 bool check(ll k){ 14 for(int i=0;i<n;i++) 15 if (a[i]+a[i+n]>k)return 0; 16 d[n]=a[0]; 17 calc(k); 18 ll lst=d[n-1]; 19 d[n]=max(d[n],d[n-1]); 20 if (d[n]>k-a[n])return 0; 21 calc(k); 22 if (lst!=d[n-1])return 0; 23 return d[2*n-1]<=k; 24 } 25 int main(){ 26 scanf("%d",&n); 27 for(int i=0;i<2*n;i++)scanf("%d",&a[i]); 28 ll l=0,r=1e15; 29 while (l<r){ 30 ll mid=(l+r>>1); 31 if (check(mid))r=mid; 32 else l=mid+1; 33 } 34 printf("%lld",l); 35 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步