牛客网小白月赛5 - I 区间

链接:https://www.nowcoder.com/acm/contest/135/I
来源:牛客网

目描述

    Apojacsleam喜欢数组。

    他现在有一个n个元素的数组a,而他要对a[L]-a[R]进行M次操作:

        操作一:将a[L]-a[R]内的元素都加上P

        操作二:将a[L]-a[R]内的元素都减去P

    最后询问a[l]-a[r]内的元素之和?

    请认真看题干及输入描述。

输入描述:

输入共M+3行:

第一行两个数,n,M,意义如“题目描述”

第二行n个数,描述数组。

第3-M+2行,共M行,每行四个数,q,L,R,P,若q为1则表示执行操作2,否则为执行操作1

第4行,两个正整数l,r

输出描述:

一个正整数,为a[l]-a[r]内的元素之和

示例1

输入

10 5
1 2 3 4 5 6 7 8 9 10
1 1 5 5
1 2 3 6
0 2 5 5 
0 2 5 8
1 4 9 6
2 7

输出

23

开始看到这道题目上去第一反应线段树模板代码,然后就陷入了内存超限和WA的死循环,从开始的30%一直到最后的%90...WA了七八次...

到后面实在想不到解决方案了就百度了一下这道题的解法, 发现原来还有前缀和这种美滋滋的东西, 简直妙蛙种子啊~~~

关键点:   因为最后只要查询一次,在过程中仅仅只需要对这一段距离进行操作,因为输入顺序的关系可以现将操作的数给保存下来,到后面在统一进行操作, 然后用一个数事先计算出L - R的和,然后每次操作就仅仅只对这个和进行操作。

秒啊~~~~~~

下面附上代码

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 1000001;
int sz[maxn];
int q[maxn],l[maxn],r[maxn],p[maxn];
int n,m;
int tl,tr;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",sz+i);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d%d",q+i,l+i,r+i,p+i);
	scanf("%d%d",&tl,&tr);
	ll sum=0;
	for(int i=tl;i<=tr;i++) sum += sz[i];
	for(int i=1;i<=m;i++){
		if(q[i] == 1) p[i] = 0-p[i];
		if(r[i]<tl || l[i]>tr) continue;
		sum += (min(r[i],tr) - max(l[i],tl) + 1)*p[i];
	}
	printf("%lld",sum);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lala__lailai/article/details/81164657
今日推荐