题目
描述 Description
FJ准备教他的奶牛们弹一首歌. 这首歌由N (1 <= N <= 50,000)个音阶组成,第i个音阶要敲击 B_i (1<= B_i <= 10,000) 次。奶牛从第0时刻开始弹, 因此他从0时刻到B_1 - 1 时刻都是敲第1个音阶,然后他从 B_1 时刻到B_1 + B_2 - 1时刻敲第2个音阶,从B_1 + B_2时刻到B_1 + B_2 + B_3- 1时刻敲第3个音阶…现在有Q (1 <= Q <= 50,000) 个问题,在时间段区间 [T, T+1)内,奶牛敲的是哪个音阶? 其中 T_i (0 <= T_i <= 整首歌的总时刻).
看下面的一首歌,第1个音阶持续2个单位时间, 第2个音阶持续1个单位时间,第3个音阶持续3个单位时间:
以下是一些询问和回答:
询问 回答的音阶
2 2
3 3
4 3
0 1
1 1
输入格式 Input Format
第 1 行:两个整数: N 、Q。
第 2…N+1行: 第i+1行只有一个整数: B_i
第N+2…N+Q+1行: 第N+i+1行只有一个整数: T_i
输出格式 Output Format
第1…Q行:对与每个询问, 在询问的时间内,奶牛敲击的是哪个音阶?
样例输入 Sample Input
3 5
2
1
3
2
3
4
0
1
样例输出 Sample Output
2
3
3
1
1
时间限制 Time Limitation
1s
注释 Hint
1s
来源 Source
usaco 09 dec silver mnotes
题解
前缀和+二分。
说明:STL里的lower_bound函数贼好用,可以减少大量代码,用处为二分查询,用法:lower_bound ( a+1 , a+n+1 , k ) - a
//a为数组,n为数组元素个数,k为要查询的数,返回值为第一个大于等于k的元素的位置,注意,a一定要为有序数列!!
而手写二分也是找到第一个大于等于k的元素的位置,+1就为这个区间敲击的音阶。但我写的是手写,没用STL。。。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
inline int read()
{
int f=1,num=0;
char ch=getchar();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
return num*f;
}
int a[maxn],n,q;
inline int search(int x)
{
int l=1,r=n;
int answer=0;
while (l<=r)
{
int mid=(l+r)>>1;
if (a[mid]<x) answer=mid,l=mid+1;
else r=mid-1;
}
return answer;
}
int main()
{
n=read(),q=read();
for (int i=1;i<=n;++i)
{
int x=read();
a[i]=a[i-1]+x;//计算前缀和
}
for (int i=1;i<=q;++i)
{
int t=read();
printf("%d\n",search(t+1)+1);
}
return 0;
}
https://blog.csdn.net/Hb_key/article/details/84403030,
推荐一个大佬的博客,三子棋的玩法。。。很棒的!!!!!!!!!