https://www.cnblogs.com/violet-acmer/p/9721160.html
一、暴力简述
首先我们不难看出,这道题--并不是一道多难的题,因为显然,第一眼看题目时便很容易地想到暴力如何打:枚举每一种订单,然后针对每一种订单,对区间内的每一天进行修改(做减法),直到某一份订单使得某一天剩下的教室数量为负数,即可得出结果。
先小小的评析一下吧:凡是能打出几近正解的暴力题,都不是难题!
但是,显然枚举形式的暴力会很慢,期望的时间复杂度约为O(m \times n)O(m×n)。
二、思想详述
让我们开动脑筋想一下:每张订单其实就可以看作是一个区间(操作),左右区间分别为开始时间和结束时间,所以这不就是一个区间操作吗——首选线段tree啦!
先介绍一种好理解、好实现的算法:差分数组。
在介绍差分之前,需要介绍前缀和思想
我们有一组数(个数小于等于一千万),并且有一大堆询问——给定区间l、r,求l、r之间所有数之和(询问个数小于等于一千万)
此处暴力肯定不行啊(O(NQlength)),那么我们来观察前缀和是怎么做的:用sum[i]来存储前i个数的和,然后用sum[r]-sum[l-1]来表示l~r之间所有数的和。(l-1原因是l~r只看要包含l)而sum数组便可以通过简单的递推求出来
代码核心:
1 for(int i=1;i<=n;i++) 2 { 3 cin>>a[i]; 4 sum[i]=sum[i-1]+a[i]; 5 } 6 for(int i=1;i<=q;i++) 7 { 8 cin>>l>>r; 9 cout<<sum[r]-sum[l-1]<<" "; 10 }