题解:AT_tkppc2016_c 有給休暇(Paid Vacation)
题目:AT_tkppc2016_c 有給休暇(Paid Vacation)
思路
首先看到这道题目,第一眼想到暴力,双重 for 循环枚举判断,统计最大值。但是!看到数据范围
那么,我们想一想学过的算法中,哪一种算法可以处理区间呢,答案是双指针,没学过的可以百度或者去b站搜,提供一个个人认为不错的 文章,或者这个 视屏,这两个都是讲了快慢指针和双向指针的,比较全面,那么为什么双指针是可以过的呢,因为快指针和慢指针都只是走完了全程,没有多走,而且每次都必定会让慢指针移动,所以总的时间复杂度就是
既然已经知道了用双指针算法,那么要用那种呢(指快慢指针和双向指针),分析题意,如果我们用快慢指针,判断这个框选的区间内个数是否小于
首先,定义一个慢指针
然后,写好模版。
while (l < r)
{
l++;
while (条件)
++r;
maxn = max(maxn, r - l);
}
接着,我们来分析一下条件。因为要保证 sum[r] - sum[l - 1] <= k(r <= n,只有同时满足这两个条件才能 ++r。
那么我们就写完了双指针的部分。
while (l < r)
{
l++;
while (sum[r] - sum[l - 1] <= k && r <= n)
++r;
maxn = max(maxn, r - l);
}
然后再讲一个细节,读入的时候,记得用异或运算取反,因为要求的是原本不放假的天数而不是放假的天数。
最后再给不了解前缀和的萌新们科普一下这道题怎么用前缀和优化。定义
ACCODE
#include <iostream>
using namespace std;
int n, k, sum[100001], maxn, l, r = 1;//sum是前缀和数组,sum[i]表示1~i天有多少天是不放假的
bool tmp;//输入用
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; ++i)
cin >> tmp, tmp ^= 1, sum[i] = sum[i - 1] + (int)tmp;//记得对输入数据用异或取反!
while (l < r)//双指针模版,思路已经讲的很清楚了吧
{
l++;
while (sum[r] - sum[l - 1] <= k && r <= n)
++r;
maxn = max(maxn, r - l);//取最大值
}
cout << maxn;
}