58.区间和
//卡码网题号58.区间和
/*
//如果我查询m次,每次查询的范围都是从0到n-1,那么该算法的时间复杂度是O(n*m),
//如果查询次数非常大的话,这个时间复杂度也是非常大的。
#include<iostream>
#include<vector>
using namespace std;
int main() {
int num,start,end;
cin >> num;
vector<int> stairx(num, 0);
for (int i = 0;i < num;i++) {
cin >> stairx[i];
}
while (cin >> start >> end) {
int sum = 0;
for (int i = start;i <= end;i++) {
sum += stairx[i];
}
cout << sum << " ";
}
return 0;
}
*/
/*
//前缀法:
//时间复杂度为O(n),后面只需要O(1)的减法操作
#include<iostream>
#include<vector>
using namespace std;
int main() {
int num,start,end,sum=0;//num为数组的长度,start是起始位置,end是终止位置,sum是0~i位置的和
cin >> num;//输入num的值
vector<int> stairx(num);//初始化数组
vector<int> stairxSum(num);//初始化数组和,stairxSum的每一个元素表示stairxSum[i]=stairx[0]~stairx[i]的和(前缀和)
for (int i = 0;i < num;i++) {//利用一个for循环赋值stairx和stairxSum
cin >> stairx[i];
sum += stairx[i];
stairxSum[i] = sum;
}
while (cin >> start >> end) {//三目运算符判断start是否为0,如果为0则没有前面一个元素,只能减到0的位置。
cout << stairxSum[end] - (start == 0 ? 0:stairxSum[start - 1]) << endl;
}
return 0;
}
*/
//C++ 代码 面对大量数据 读取 输出操作,最好用scanf 和 printf,耗时会小很多:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, a, b;
cin >> n;
vector<int> vec(n);
vector<int> p(n);
int presum = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &vec[i]);
presum += vec[i];
p[i] = presum;
}
//函数返回值为 int 型。如果a和b都被成功读入,那么 scanf 的返回值就是2;
//如果只有a被成功读入,返回值为1;
//如果a和b都未被成功读入,返回值为0;
//如果遇到错误或遇到end of file,返回值为EOF。end of file为Ctrl + z 或者Ctrl + d。其中EOF的值为 - 1
//也就是说 scanf 返回值只有为EOF的时候,也就是-1的时候取反才是0(-1的补码表示全是1,按位取反后全是0,即为假),
//才会正常退出循环,其他情况均不会正常退出循环(可能会报错)
while (~scanf("%d%d", &a, &b)) {
int sum;
if (a == 0) sum = p[b];
else sum = p[b] - p[a - 1];
printf("%d\n", sum);
}
return 0;
}
验证~scanf的结果
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a, b;
//验证一个的时候注意注释掉另外一个
//cout << scanf("%d%d", &a, &b);
cout << ~scanf("%d%d", &a, &b);
return 0;
}
如果a和b都被成功读入
那scanf 的返回值就是2
~scanf的返回值为-3。
如果只有a被成功读入
那scanf 返回值为1,
~scanf 返回值为-2
如果a和b都未被成功读入
那scanf 返回值为0,
~scanf 返回值为-1
如果遇到错误或遇到end of file(Ctrl+z)
那scanf 返回值为EOF(-1)
~scanf 返回值为0
注意:为什么这里连续用了三个Ctrl+z?根据网上的某个结论:
ctrl+z类似于一个带有指令的字符,而整形和浮点型无法接收字符,但其拥有指令,他可以让原本不能接收字符的%d变为接受字符。在接收到ctrl+z字符后scanf函数内部可能需要再接收一个ctrl+z指令执行ctrl+z字符,才能返回EOF,而%c本就能就收字符,所以只需要输入2个ctrl+z。那为什么猜测ctrl+z是字符呢,是因为我用getchar函数来接收他的值,发现只用输入一次就可以输出EOF,但是也许函数内部已经定好把ctrl+z转化为EOF,所以不敢肯定ctrl+z的字符型参数一定为-1。
当我们把代码改变为
得到结果:
结果验证了上面网友的猜想。
验证cin的结果
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a, b;
cin>>a>>b;
cout << cin.get();
return 0;
}
当输出正确时,
当输入错误时,
cin是C++的输入流对象,">>"是重载的运算符,cin>>的返回值是cin对象。用这个当条件的话,通过检测其流的状态来判断结束;
(1)若流是有效的,即流未遇到错误,那么检测成功;
(2)若遇到文件结束符,或遇到一个无效的输入时(例如本题输入的第二个值不是一个整数),istream对象的状态会变为无效,条件就为假;读取失败的时候,就不能继续读取了,那么读取操作结束,cin.get()就返回-1,跳出程序!