Processing math: 100%

[atARC117F]Gateau

假设序列bi为最终第i片上的草莓数,即需要满足:0i<2n,ain1j=0b(i+j)mod 2n

要求最小化2n1i=0bi,显然增大bi一定仍满足条件,即具备单调性,二分并判断其是否可以为X

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

1.0i<n,ain1j=0bi+j

2.ni<2n,ai2n1j=ibj+in1j=0bj,考虑后者中不被计算的是一个连续区间,可以用X减去这一段,即Xi1j=in1bj,移项后即i1j=inbjXai

两部分分别限制了上下限,即条件也可以写作:0i<n,ain1j=0bi+jXai+n

对其求前缀和,令Si=i1j=0bj,即要求aiSi+nSiXai+n

另一方面,根据bi0,还要求SiSi+1(特别的,要求S0=0以及S2n1X

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

将之变形,最终所有条件都可以写作Si+xSj,即差分约束的形式

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

另外,有正环或最终d2n1>X即无解(这里最长路才是S2n1的最小值)

由于有正权边(求最长路),只能使用spfa,以及最外层的二分,复杂度为o(n2logA),且会被卡

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

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

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

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

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

(另外更新Sn后,还需要判断是否满足SnXan

这一做法复杂度o(nlogA),可以通过

复制代码
 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
复制代码

 

posted @   PYWBKTDA  阅读(429)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示