标签:upper 序列 pos 代码 ide 答案 bsp read opened
因为求最大时间的最小,考虑到二分答案。
常规思路:断环为链,二倍链。
最暴力的做法是在n个位置都断一次环,序列for一遍暴力分组,大于mid了就分到下一组,时间O(n^2 logn)
考虑优化:
我们发现每一次暴力分组是把整个序列都给走了一遍,分好的组满足和<=mid,与其一个个的把值加到和里,不如先处理出前缀和,然后对于每一个组的起点,二分找出这个组的终点(我代码中是用upper_bound实现的)
int s=t[q],c=1;//s即为起点 int flagg=0; for(int i=q;i<=q+n-1;++i) { if(c>mid){flagg=1;break;} if(t[i]>mid)return 1; int v=mid-s;//还有这么多才到mid v+=sum[i];//在前缀和数组中查找,所以加上sum[i] int pos=upper_bound(sum+i,sum+2*n+1,v)-sum;//在i之后进行寻找 if(pos>q+n-1)break; i=pos-1;//循环完后还要++i,所以这里i=pos-1 if(t[pos]<=mid)s=t[pos],c++; else return 1; }
然鹅这样最后的点还是会T,再考虑优化
我们在每次的新断的链进行操作前加了一句这样的话:
if(sum[q]>mid)return 1;
即起点的前缀和小于mid的话,这样断开的链一定是不满足的。
为什么?
我们看这样一组数据
假如二分的答案mid=11
试着模拟一下算法过程,断的链分别是
1 5 2 7 8
5 2 7 8 1
2 7 8 1 5
到7 8 1 5 2这一组时一定是不满足的(假设前面的也不满足所以一直向后走)
因为1 5 2 7 8是不满足的(且1 5 2 分为了一组),所以才会往后断环,到了7 8 1 5 2 仍是会1 5 2 分为一组还是不满足,就相当于是把1 5 2 7 8 分成的组调了一下顺序而已。
#include<bits/stdc++.h> #define N 50003 #define M 3003 #define INF 2100000000 using namespace std; int read() { int x=0,f=1;char s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x*f; } int t[2*N],sum[N*2],n,m; int check(int mid) { int q=1; while(q<=n) { if(sum[q]>mid)return 1;//!!!当前面的前缀和>mid还不成功,这种情况在开始枚举时已经失败,于是此mid不成立 int s=t[q],c=1;//s即为起点 int flagg=0; for(int i=q;i<=q+n-1;++i) { if(c>mid){flagg=1;break;} if(t[i]>mid)return 1; int v=mid-s;//还有这么多才到mid v+=sum[i];//在前缀和数组中查找,所以加上sum[i] int pos=upper_bound(sum+i,sum+2*n+1,v)-sum;//在i之后进行寻找 if(pos>q+n-1)break; i=pos-1;//循环完后还要++i,所以这里i=pos-1 if(t[pos]<=mid)s=t[pos],c++; else return 1; } if(flagg==0&&c<=m&&s<=mid)return 0; q++;//重新断环 } return 1; } int main() { // freopen("dinner.in","r",stdin); // freopen("dinner.out","w",stdout); n=read(),m=read(); int l=0,r=0; for(int i=1;i<=n;++i) { t[i]=read(); sum[i]=sum[i-1]+t[i]; r+=t[i]; } for(int i=n+1;i<=2*n;++i) t[i]=t[i-n],sum[i]=sum[i-1]+t[i]; int ans; while(l<r) { int mid=(l+r)>>1; if(check(mid))l=mid+1; else ans=mid,r=mid; } printf("%d\n",ans); } /* 5 5 1 2 5 4 3 5 2 1 5 2 7 8 10 4 1 3 5 2 7 8 2 1 2 4 */
也还有倍增的做法
2019暑假集训8.22(problem2.dinner)(二分)
标签:upper 序列 pos 代码 ide 答案 bsp read opened
原文地址:https://www.cnblogs.com/yyys-/p/11395983.html