一本通1603绿色通道
1603:绿色通道
时间限制: 1000 ms 内存限制: 524288 KB【题目描述】
高二数学《绿色通道》总共有 n 道题目要抄,编号 1…n,抄第 i 题要花 ai 分钟。小 Y 决定只用不超过 t 分钟抄这个,因此必然有空着的题。每道题要么不写,要么抄完,不能写一半。下标连续的一些空题称为一个空题段,它的长度就是所包含的题目数。这样应付自然会引起马老师的愤怒,最长的空题段越长,马老师越生气。
现在,小 Y 想知道他在这 t 分钟内写哪些题,才能够尽量减轻马老师的怒火。由于小 Y 很聪明,你只要告诉他最长的空题段至少有多长就可以了,不需输出方案。
【输入】
第一行为两个整数 n,t。
第二行为 n 个整数,依次为 a1,a2,…,an。
【输出】
输出一个整数,表示最长的空题段至少有多长。
【输入样例】
17 11
6 4 5 2 5 3 4 5 2 3 4 5 2 3 6 3 5
【输出样例】
3
【提示】
数据范围与提示:
对于 60% 数据,n≤2000;
对于所有数据,0<n≤5×104,0<ai≤3000,0<t≤108 。
sol:可以发现这道题与烽火传递有很像的东西,于是可以二分答案,然后O(n)判断这个答案所用的时间与 t 的关系即可
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } inline void writeln(ll x) { write(x); putchar('\n'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) writeln(x) const int N=50005,inf=0x3f3f3f3f; int n,T,Tim[N],dp[N]; struct Record { int Shuz,Weiz; }Ddq[N]; inline bool Jud(int mid) { memset(dp,63,sizeof dp); dp[0]=0; int i,Head=0,Tail=0; Ddq[Head].Shuz=Ddq[Head].Weiz=0; for(i=1;i<=n;i++) { while(Head<Tail&&Ddq[Head].Weiz<i-mid-1) Head++; dp[i]=dp[Ddq[Head].Weiz]+Tim[i]; while(Head<=Tail&&dp[i]<Ddq[Tail].Shuz) Tail--; Ddq[++Tail]=(Record){dp[i],i}; } int ans=inf; for(i=max(n-mid,1);i<=n;i++) ans=min(ans,dp[i]); return (ans<=T)?1:0; } int main() { // freopen("gp2.in","r",stdin); int i; R(n); R(T); for(i=1;i<=n;i++) R(Tim[i]); int l=0,r=n; while(l<=r) { int mid=(l+r)>>1; if(Jud(mid)) r=mid-1; else l=mid+1; } Wl(l); return 0; } /* input 17 11 6 4 5 2 5 3 4 5 2 3 4 5 2 3 6 3 5 output 3 */
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!