58.区间和

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,跳出程序!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值