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;
}
posted @ 2025-04-16 20:26  LteShuai  阅读(12)  评论(0)    收藏  举报