数列
内存限制: 256 MiB 时间限制: 1000 ms 标准输入输出 题目类型: 传统 评测方式: 文本比较
题目描述
小 Q 被一个数列迷住了。他发现这个数列可以分为连续的 N 段,其中第 i 段是连续 ai 个 pi 。小 Q 在想有没有快速求数列第 K 项的方法呢?于是他开始不断尝试计算数列第 ki 项的值,但计算量太大,小 Q 想用程序来实现自动计算,你来帮帮他吧。
输入格式
第一行有一个整数 N,表示数列分为 N 个重复段。 接下来有 N 行,每行有两个整数 ai,pi, 表示第 i 段重复了 ai 个 pi。 第 N+2 行有一个整数 M,表示小 Q 有 M 个查询。 接下来有 M 个整数 ki,表示小 Q 需要计算数列中第 ki 项的值。
输出格式
输出数据有 M 个,每个数依次对应了小 Q 一次查询的结果。
样例
样例输入
复制2
5 1
3 2
3
1 4 8
样例输出
复制1 1 2
样例解释
数列有 2 个重复段如下:
1 1 1 1 1 2 2 2
小 Q 有 3 个查询,分别查询第 1 项、第 4 项和第 8 项。
查询结果为:数列中第 1 项的值为 1,第 4 项的值为 1,第 8 项的值为 2。
数据范围与提示
60%的数据 1 <= N <=1000 , 1<=ai<=1000 , 1<=pi<=1000 ,1<=M<=1000 ,1<=ki<=10^6。
100%的数据 1 <= N <=100000 , 1<=ai<=10^6, 1<=pi<=106 ,1<=M<=10000,1<=ki<=10^9。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7 + 5;
long long n, m, x, l, r, mid;
long long a[maxn], b[maxn], sum[maxn];
int main() {
scanf("%lld", &n);
for(int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
sum[i] = sum[i - 1] + a[i];
scanf("%lld", &b[i]);
}
scanf("%lld", &m);
for(int i = 1; i <= m; i++) {
scanf("%lld", &x);
l = 1, r = n;
while(l < r) {
mid = (l + r) / 2;
if(sum[mid] >= x) {
r = mid;
} else {
l = mid + 1;
}
}
printf("%lld ", b[l]);
}
return 0;
}