[SET维护DP] Codeforces #875E. Delivery Club

来源:互联网 发布:杨紫宁丹琳 知乎 编辑:程序博客网 时间:2024/06/05 03:46

好题。首先不难想到二分答案。验证就是写出状态 n2DP,类似 二取一维数组 的搞法:
fi,j 表示前 i 个点已走过,两个人分别在 ij, (i>j)
fi,jfi+1,j(ai+1ajmid),fi,jfi+1,i(ai+1aimid)
怎么优化呢? 可以发现这个 DP 很特殊,他是布尔形的,且转移方程很有特点,当 i 推一层时,从 01 的只可能是 fi+1,i,然后就是某些 1 会变成 0
所以我们就可以用 set 维护 DP。即开个 set 维护哪些 j1
复杂度 O(nlogn)

#include<cstdio>#include<cmath>#include<set>#include<algorithm>using namespace std;const int maxn=200005;set<int> S; int n,a[maxn],ans;bool check(int lim){    if(abs(a[1]-a[2])>lim) return false;    S.clear(); S.insert(a[1]);     for(int i=3;i<=n+2;i++){        S.insert(a[i-1]);        while(!S.empty()&&abs(a[i]-(*S.begin()))>lim) S.erase(*S.begin());        while(!S.empty()&&abs(a[i]-(*S.rbegin()))>lim) S.erase(*S.rbegin());        if(S.empty()) return false;    }    return true;}int main(){    freopen("cf875E.in","r",stdin);    freopen("cf875E.out","w",stdout);    scanf("%d%d%d",&n,&a[1],&a[2]);    for(int i=3;i<=n+2;i++) scanf("%d",&a[i]);    int L=0,R=1e9;    while(L<=R){        int mid=(L+R)>>1;        if(check(mid)) R=mid-1, ans=mid;                  else L=mid+1;     }    check(1);    printf("%d\n",ans);} 
原创粉丝点击