zoukankan      html  css  js  c++  java
  • [ARC117F]Gateau

    假设序列$b_{i}$为最终第$i$片上的草莓数,即需要满足:$forall 0le i<2n,a_{i}le sum_{j=0}^{n-1}b_{(i+j)mod 2n}$

    要求最小化$sum_{i=0}^{2n-1}b_{i}$,显然增大$b_{i}$一定仍满足条件,即具备单调性,二分并判断其是否可以为$X$

    为了避免取模,将条件分为$0le i<n$以及$nle i<2n$两部分,分别可以写作:

    1.$forall 0le i<n,a_{i}le sum_{j=0}^{n-1}b_{i+j}$

    2.$forall nle i<2n,a_{i}le sum_{j=i}^{2n-1}b_{j}+sum_{j=0}^{i-n-1}b_{j}$,考虑后者中不被计算的是一个连续区间,可以用$X$减去这一段,即$X-sum_{j=i-n-1}^{i-1}b_{j}$,移项后即$sum_{j=i-n}^{i-1}b_{j}le X-a_{i}$

    两部分分别限制了上下限,即条件也可以写作:$forall 0le i<n,a_{i}le sum_{j=0}^{n-1}b_{i+j}le X-a_{i+n}$

    对其求前缀和,令$S_{i}=sum_{j=0}^{i-1}b_{j}$,即要求$a_{i}le S_{i+n}-S_{i}le X-a_{i+n}$

    另一方面,根据$b_{i}ge 0$,还要求$S_{i}le S_{i+1}$(特别的,要求$S_{0}=0$以及$S_{2n-1}le X$)

    同时,上面这两个条件也是充分条件,问题即判断是否存在满足上述条件的$S_{i}$

    将之变形,最终所有条件都可以写作$S_{i}+xle S_{j}$,即差分约束的形式

    更具体的来说,建有向边$(i,j,x)$并从0开始求最长路,令$d_{i}$为到$i$的最长路,即满足此条件

    另外,有正环或最终$d_{2n-1}>X$即无解(这里最长路才是$S_{2n-1}$的最小值)

    由于有正权边(求最长路),只能使用spfa,以及最外层的二分,复杂度为$o(n^{2}log A)$,且会被卡

    事实上,由于这张图的特殊性,有如下做法:

    如果将$(n-1,n,0)$这条边删去,将整张图看作上下两行,分别为$[0,n)$和$[n,2n)$,图的结构即比较简单,仅包含上下两行对应点之的有环,以及两行向后的边

    此时将两个对应点的最长路一起算,即没有了后效性,可以$o(n)$求出

    (特别的,若$a_{i}+a_{i+n}>X$即存在两个对应点之间的正环,即无解)

    加入这条边后,在没有正环的情况下,先忽略这条边求出最长路,再加入这条边后用$S_{n-1}$更新$S_{n}$并重复一次求最长路(仍然忽略这条边),若$S_{n-1}$发生变化必然存在正环,否则即求出了最长路

    (另外更新$S_{n}$后,还需要判断是否满足$S_{n}le X-a_{n}$)

    这一做法复杂度$o(nlog A)$,可以通过

     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 }
    View Code
  • 相关阅读:
    前端 HTML
    python3内置函数
    内置函数的随机验证码
    线程、进程以及协程,上下文管理器
    线程池的定义方法
    python_控制台输出带颜色的文字方法
    while 循环 continue break 用法例子
    JVM 基础知识
    ios 设置状态栏文本颜色为白色
    ios 常用第三方库要加的framework,ARC的设置
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14678951.html
Copyright © 2011-2022 走看看