今天我给大家出一套C++算法-尺取法考题
限时50分钟小时,大家加油!!!
尺取法.理论知识(不是题目)
记 (l,r) 两个端点为一个序列内以 l 为起点的最短合法区间,如果 r 随 l 的增大而增大的话,我们就可以使用尺取法。
具体的做法是:
-
初始化左右端点
-
不断扩大右端点,直到满足条件
-
如果第二步中无法满足条件,则终止,否则更新结果
-
将左端点扩大1,然后回到第二步
因为 r 随 l 增大而增大,所以 r 只有 n 次变化的机会,所以时间复杂度为 O(n) 。
经典例子
给定一个长度为 n 的数列 a_1, a_2, ..., a_na1,a2,...,an 及整数 S ,求不小于 S 的连续子序列的和的最小值,假设解肯定存在。
input
n=10,S=15
a= {5,1,3,5,10,7,4,9,2,8}
题目1:队伍(NHOI2016xy6)
题目描述
蛋糕分好了,小朋友排着队去领蛋糕。铭铭想从 N 人的队伍中选出 K 位小朋友帮忙分发蛋糕。但铭铭选人的方法有点特别,他想从队伍中选连续的 K 个小朋友,而且必须是男比女多,你知道铭铭有多少种选择吗?
输入格式
第一行,两个整数 N,代表队伍中有 N ( 0 < N <= 1000000 )个小朋友,铭铭想选 K ( K < N )个人。
第二行:有 N 个 0 或 1(0 代表男,1 代表女),每个数用空格隔开。
数据范围
50% 的数据 0 < N < 1000 , k < N ;
80% 的数据 0 < N < 1000000 , k <= 100 ;
100% 的数据 0 < N < 1000000 , k < N ;
输出格式
一个整数。代表铭铭可以有多少种选择方案。
样例
输入数据 1
10 3
0 1 1 0 1 0 0 1 0 1
输出数据 1
4
完成程序
#include<bits/stdc++.h>
using namespace std;
int n,k,a[1000002],c=0;
long long ans;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]+=a[i-1]; //求女孩子数的前缀和
}
for(int x=1,y=填空(1);y<=填空(2);x++,填空(3) ) // k个人位置不断往右挪
{
int s=a[y]-a[x-1]; //s表示从 x 到 y 的女孩子个数
if(填空(4)>s) c++; //总人数减女孩,就是男孩。如果男生数量大于女生,合条件。
}
cout<<c;
return 0;
}
Copy
填空(1):
填空(2):
填空(3):
填空(4):
题目2:松果(DLOI2016xjt)
题目描述
大森林有熊兄弟的好朋友松鼠蹦蹦,一天蹦蹦来到一条很长的小 路,发现沿路地上都有松果,高兴极了,决定尽可能多吃松果。
蹦蹦观察到,每个松果的重量并不一定相同,可蹦蹦的肚子容量 有限,总共最多只能吃重量 C 的松果。
蹦蹦吃东西有个特点,一旦开吃就会不停的吃,不会漏过路上碰 到松果,直到遇到一个吃不下或吃完停止。也就是说松鼠蹦蹦只会吃 连续一段的松果。
已知路上共有 N 个松果,顺序的重量是 w_1, w_2,..., w_nw1,w2,...,wn 。蹦蹦最多可能吃多少颗松果?
输入格式
第一行,二个正整数,空格分开,表示 N 和 C,N 范围在[1..50000], C 范围在[1..1000000]。
第二行,N 个正整数,空格分开,表示从 w_1、w_2,..., w_nw1、w2,...,wn ,即松果的重量。每个松果重 量范围在[1..1000]。
数据范围
一个正整数,蹦蹦可以吃到的最多松果数量。
输出格式
样例
输入数据 1
5 5
3 1 2 1 1
输出数据 1
4
输入数据 2
9 5
1 5 4 3 2 1 1 4 1
输出数据 2
3
样例解释
样例 1 :吃:(1,2,1,1)这段的松果。
样例 2 :吃:(2,1,1)这段的松果。
完成程序
#include<bits/stdc++.h>
using namespace std;
int n,c,a[50002],ma=0,s=0;
long long ans;
int main()
{
cin>>n>>c;
for(int i=1;i<=n;i++) cin>>a[i];
for(int x=1,y=填空(1);y<=n;y++)
{
s += 填空(2); // x 到 y 的松果总重量
填空(3) (s>c) s-= a[x++]; //移动 x 收缩区间
ma=max(填空(4),ma); //求最长区间长度
}
cout<<ma;
return 0;
}
填空(1):
填空(2):
填空(3):
填空(4):
题目3:求和为C
题目描述
楠楠在网上刷题,感觉第一题:求两数的和 (A+B Problem) 太无聊了,于是增加了一题:求和为 C 的Problem,难倒了一群小朋友,哈哈。
题目是这样的:给出 N 个正整数,一个值 C ,要求在这 N 个整数中找一段连续的数(至少 2 个数),使得它们的和等于 C ,问这样的方案有多少种?
例如:N=8,C=7,8 个整数是:2 5 1 1 2 4 7 1。答案是3。具体方案:(2, 5)、(5,1,1)、(1,2,4)。
输入格式
第一行 2 个正整数:N , C 。
第二行:N 个正整数。
数据范围
N 的范围是 [1...100,000]。
C 的范围是 [1...1,000,000,000]。
N 个整数中每个数的范围是:[ 1...1,000,000,000]。
输出格式
一个整数,表示该串数中包含的所有方案数。
样例
输入数据 1
4 5
1 4 1 4
输出数据 1
3
题目4: 黑白奶牛(NHOI2016xjt4)
题目描述
有 N 只奶牛从左往右排成一行,编号是 1 至 N 。这 N 只奶牛当中,有一些奶牛是黑色的,其余的是白色的。
color[i] 表示第 i 只奶牛的颜色,如果 color[i]=0 则表示第 i 头奶牛是黑色的,如果 color[i]=1 则表示第 i 头奶牛是白色的。
六一奶牛儿童节快到了,农场主 Farmer John 要从这 N 头奶牛当中,挑选尽可能多的奶牛去参加晚会。
Farmer John 挑选奶牛的原则是:挑选编号是连续的一段奶牛,这一段奶牛的颜色必须全部是白色的。
Farmer John 有一个魔法棒,每用一次魔法棒就可以把一头黑色的奶牛变成一头白色的奶牛,魔法棒最多只能使用 K 次。
在上述条件下,最多可以有多少头奶牛去参加晚会呢?
输入格式
第一行,两个整数,N 和 K。
第二行,N 个整数,第 i 个整数就是 color[i] , color[i] 要么是 0,要么是 1。
数据规模
对于 50% 的数据,1 <= N <= 1000,K = 0 ,即不能使用魔法棒。
对于 100% 的数据,1 <= N <= 100000, 1 <= K <=N。
输出格式
一个整数,表示最多有多少头奶牛可以去参加晚会。
样例
输入数据 1
11 0
1 1 0 0 1 1 1 1 0 1 1
输出数据 1
4
输入数据 2
11 1
1 1 0 0 1 1 1 1 0 1 1
输出数据 2
7
样例解释
样例 1 :由于 K=0,所以不能使用魔法棒,所以挑选编号是 5 至 8 的奶牛去参加晚会。
样例 2 :由于 K=1,所以最多可以使用 1 次魔法棒,使用魔法棒把第 9 头奶牛变成白色奶牛,然后挑选编号是 5 至 11 的奶牛去参加晚会。
题目1答案:
代码
'1': k
'2': 'n'
'3': y++
'4': k-s
题目2答案:
代码
'1': '1'
'2': a[y]
'3': while
'4': y-x+1
题目3答案:
代码
#include<bits/stdc++.h>
using namespace std;
int n,c,a[100002],ma=0,m=0;
long long ans;
int main()
{
cin>>n>>c;
for(int i=1;i<=n;i++) cin>>a[i];
ma=ma+a[1];
for(int x=1,y=2;y<=n;y++)
{
ma+=a[y];
while(ma>c)
{
ma-=a[x++];
}
if(ma==c&&y-x>0)
{
ans++;
}
}
cout<<ans;
return 0;
}
题目4答案:
代码
#include<bits/stdc++.h>
using namespace std;
int n,l,k,b[100000],a[100000],sum=0,ma=0;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>b[i];
a[i]=a[i-1];
if(b[i]==0) a[i]++;
}
for(int i=1;i<=n;i++)
{
if(a[i]-a[l]<=k)
{
sum++;
if(i==n&&sum>ma)
{
ma=sum;
}
}
else
{
if(sum>ma)
{
ma=sum;
}
l++;
}
}
cout<<ma;
return 0;
}
标签:松果,int,样例,C++,考题,取法,填空,ma,奶牛
From: https://blog.csdn.net/zhangguanghao9/article/details/144024547