C. Helping the Nature
题意:给定一个长度为
n
n
n 的数组。每次可以有以下三种操作:
①可以取一个数组下标
i
(
1
≤
i
≤
n
)
i(1\le i \le n)
i(1≤i≤n) ,然后让
[
1
,
i
]
[1,i]
[1,i] 的所有数减一;
②可以取一个数组下标
i
(
1
≤
i
≤
n
)
i(1\le i \le n)
i(1≤i≤n) ,然后让
[
i
,
n
]
[i,n]
[i,n] 的所有数减一;
③让整个数组所有数都加1。
问至少操作几次,可以使得整个数组所有元素为0。
思路:
1.整个区间同时加或减同一个数,可以想到用差分。将三个操作转化为对差分数组的三个操作:
①
a
1
a_1
a1 减一,
a
i
+
1
a_{i+1}
ai+1加1;
②
a
i
a_i
ai 减一,
a
n
+
1
a_{n+1}
an+1加1;
③
a
1
a_1
a1 加一,
a
n
+
1
a_{n+1}
an+1减1。
可以看到对1号位置减一(同时不影响其他位置)的操作只有②,对1号位置加一(同时不影响其他位置)的操作只有③;对除1号位置减一的操作只有②,对除1号位置加一的操作只有①。操作的方式是唯一的。
2.要让整个数组所有元素变为0,等价于让原数组的差分数组所有元素变为0。
代码:
#include <bits/stdc++.h>
using namespace std;
#define il inline
#define pb push_back
#define fi first
#define se second
#define int long long
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=1e-6;
const int mod=1e7+7;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
int T,n,a[N],c[N];
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>T;
// T=1;
while(T--){
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i) c[i]=a[i]-a[i-1];
int ans=0;
for(int i=2;i<=n;++i){
if(c[i]<0) {
ans-=c[i];
c[1]+=c[i];
}
else ans+=c[i];
}
ans+=abs(c[1]);
cout<<ans<<'\n';
}
}
D. River Locks
题意:给定一个长度为
n
n
n 的序列,每一个位置的值
a
i
a_i
ai 代表第
i
i
i 个位置的水槽的体积,每个水槽正上方有一个泵,打开泵可以向水槽注水,第
i
i
i 个水槽满了,多出的水会流向第
i
+
1
i+1
i+1 个水槽里,第
i
+
1
i+1
i+1 个水槽满了,多出的水会流向第
i
+
2
i+2
i+2 个水槽,以此类推,当第
n
n
n 个水槽满了,多出的水就流向河流,即浪费了。有
q
q
q 次询问,每次询问给定一个一个时间
t
t
t,问要在
t
t
t 时间内灌满所有水槽,至少需要开多少个泵,如果
t
t
t 时间内不可灌满所有水槽,输出-1。
思路:
1.优先选择上游的泵,这样多出来的水会流向后面的水槽。
2.对于每次询问给定的
t
t
t 。首先,显然,需要的泵的数量=
⌈
s
u
m
t
⌉
\left \lceil \frac{sum}{t} \right \rceil
⌈tsum⌉,
s
u
m
sum
sum 为
n
n
n 个水槽总体积,即,需要
⌈
s
u
m
t
⌉
\left \lceil \frac{sum}{t} \right \rceil
⌈tsum⌉ 个泵,这样才能在
t
t
t 时间内流到
s
u
m
sum
sum 体积水,但有了
⌈
s
u
m
t
⌉
\left \lceil \frac{sum}{t} \right \rceil
⌈tsum⌉ 个泵,不一定就能在
t
t
t 时间内灌满水槽,还要考虑一个时间下界,比如样例:
4
4
4 个水槽的体积分别为
6
,
1
,
1
,
1
6,1,1,1
6,1,1,1,给定时间
t
=
5
t=5
t=5。这个下界应该是:
max
k
=
1
∼
n
⌈
∑
i
=
1
k
a
i
k
⌉
\max_{k=1\sim n} \left \lceil \frac{\sum_{i=1}^{k}a_i}{k} \right \rceil
maxk=1∼n⌈k∑i=1kai⌉。
代码:
#include <bits/stdc++.h>
using namespace std;
#define il inline
#define pb push_back
#define fi first
#define se second
#define int long long
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=1e-6;
const int mod=1e7+7;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
int T,n,q;
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// cin>>T;
T=1;
while(T--){
cin>>n;
int sum=0;
int t,tt;
int mx=0; //处理出最少需要的时间
for(int i=1;i<=n;++i){
cin>>t;
sum+=t;
tt=ceil(sum*1.0/i);
mx=max(tt,mx);
}
cin>>q;
int cnt;
while(q--){
cin>>t;
cnt=ceil(sum*1.0/t);
if(cnt>n) cout<<-1<<'\n'; //需要大于n个泵的肯定不行
else { //如果需要的泵<=cnt,只有在t>=mx时,才可以。
if(t>=mx) cout<<cnt<<'\n';
else cout<<-1<<'\n';
}
}
}
}