CodeForces-Watering an Array
题目

不会写
前言
这道题 题目就需要好好读几遍,要明白 v数组中的每一个值都是小于n的
然后就是v的大小是k,并且k<=1e5,
其次就是d很大,题目给的是压缩循环数组,所以在遍历
的过程中想到要用%k去解决这个问题
然后这道题目 我个人认为蛮难的,我是真的写不来。哎,一看到这种玩意就头疼。不过cf的题目其实都是有规律的,这道题也是,毕竟纯模拟的题目思维简单,cf不屑于出吧。
思路
真不知道大家怎么发现的 在reset操作完之后发现种菜一次收菜一次是最好的选择,确实是这样的,种一次必得一次贡献,种两次就不一定了,可能有一次吧,毕竟得看v数组得脸色,以此类推,就是种一次收一次最好
然后就是分析什么时候开始reset操作 这一步很关键,我也觉得最难,md,一个黄题有这么麻烦吗,这不成绿了吗,
坑点在于循环次数,首先小于d,其次小于等于2n,不能等于d,不然你一天又收又种的,
为什么小于等于2n,就是数组长度为n,最多n贡献嘛,就是说在reset之前的时候,超过2*n,还不如一开始就种一次收一次呢,不然浪费天数了,然后很多人会想到循环n次 即可,这也不行的,
如果b是4 1 1 1...1这种呢,a是0
0 1 2 ,要加两次的这种,b注定要跑两次的,一次不
够,所以要2*n,找到2,2,3,4这个情况,贡献为3, 比2大,可以选择。但是再超过8,就不要了,不过这个数据最优解是4,种一次收一次最好,只是说这么个道
理。
然后代码写起来很简单的注意那个(i-1)%k+1,
就是因为出现k=1的时候,我v数组下标是1,v[0]没有
值的,最后就是小于d天了,好了,不写了,这题我认
为是绿,而且不是水绿。
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
ll a[2005];
ll v[100005];
ll cnt[4020];
void solve() {
int n, k, d;
cin >> n >> k >> d;
memset(cnt, 0, sizeof cnt);
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (a[i] == i)cnt[0]++;
}
// cout<<cnt[0]<<" sdsd"<<endl;
for (int i = 1; i <= k; i++)cin >> v[i];
for (int i = 1; i <= 2 * n && i < d; i++) {
//不能等于d否则一天又种又收
//也不能i<=2*n,i<d,会忽略前面那个条件
//可以 for(int i=1;i<=2*n,i<=d;i++)?
for (int j = 1; j <= v[(i-1) % k+1]; j++)a[j]++;
for (int h = 1; h <= n; h++) if (a[h] == h)cnt[i]++;
// cout<<cnt[i]<<" "<<i<<endl;
}// 当k为1 不能直接i%k 因为下标1开始 除非为0
long long ans=0;
for(int i=0;i<=2*n&&i<=d;i++)
{
ans=max(ans,cnt[i]+(d-i-1)/2);
}
cout<<ans<<endl;
return ;
}
int main() {
int t;
cin >> t;
while (t--)solve();
return 0;
}

浙公网安备 33010602011771号