题目大意:
n n n个水槽体积是 v v v, q q q个查询,每次给定注水时间 t i ti ti,问最小需要同时开几个水管,在 t i ti ti前注满所有水槽。(一个水槽注满会向下一个转移时间是0)
思路:
时间考虑到
t
i
ti
ti(没什么好说的)
设选了
x
x
x个水槽,那这
x
x
x个水槽最好选在
1
−
x
1-x
1−x。(水满转移不需要时间,转移只能向后,优先满足左边)
那不就是总体积除于
t
i
ti
ti上取整??
是但不完全是!要满足选的前
x
x
x个水槽在
t
i
ti
ti时刻都已充满,否则就是
−
1
-1
−1。(为什么不扩大
x
x
x这个以后说)
d
p
[
i
]
dp[i]
dp[i]记录的是充满前
i
i
i个水槽的最段时间。
d
p
[
1
]
=
v
[
1
]
dp[1]=v[1]
dp[1]=v[1]
在第
i
i
i个水槽时,直接在
d
p
[
i
−
1
]
dp[i-1]
dp[i−1]的时间基础上二分即可。
void work(){
dp[1]=v[1],sum[1]=v[1];
for(int i=2;i<=n;i++){
sum[i]=sum[i-1]+v[i]; // 前缀和
ll l=dp[i-1],r=1e9;
while(l<r){
ll mid=l+r>>1;
if(mid*i-sum[i-1]>=v[i]) r=mid; // 前i-1都已满足,余下的水一定可以转移
else l=mid+1;
}
dp[i]=l;
}
}
不难发现,整个 d p dp dp数组是非严格上升的,故当最小的 x x x不满足时,答案是 − 1 -1 −1.
Code
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=2e5+10;
ll n,dp[N],v[N],sum[N];
void work(){
dp[1]=v[1],sum[1]=v[1];
for(int i=2;i<=n;i++){
sum[i]=sum[i-1]+v[i];
ll l=dp[i-1],r=1e9;
while(l<r){
ll mid=l+r>>1;
if(mid*i-sum[i-1]>=v[i]) r=mid;
else l=mid+1;
}
dp[i]=l;
}
}
int main(){
guo312;
cin>>n;
for(int i=1;i<=n;i++){
cin>>v[i];
}
work();
int q; cin>>q;
while(q--){
ll ti; cin>>ti;
ll ans=sum[n]/ti;
if(sum[n]%ti) ans++;
if(dp[ans]<=ti&&ans<=n) cout<<ans<<endl;
else cout<<"-1"<<endl;
}
return 0;
}
代码
r
e
re
re了???
注意在判断输出时是且运算符,要先判断答案是否小于等于
n
n
n。
AC代码
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=2e5+10;
ll n,dp[N],v[N],sum[N];
void work(){
dp[1]=v[1],sum[1]=v[1];
for(int i=2;i<=n;i++){
sum[i]=sum[i-1]+v[i];
ll l=dp[i-1],r=1e9;
while(l<r){
ll mid=l+r>>1;
if(mid*i-sum[i-1]>=v[i]) r=mid;
else l=mid+1;
}
dp[i]=l;
}
}
int main(){
guo312;
cin>>n;
for(int i=1;i<=n;i++){
cin>>v[i];
}
work();
int q; cin>>q;
while(q--){
ll ti; cin>>ti;
ll ans=sum[n]/ti;
if(sum[n]%ti) ans++;
if(ans<=n&&dp[ans]<=ti) cout<<ans<<endl;
else cout<<"-1"<<endl;
}
return 0;
}