题解 P2781 【传教】
题解 P2781 【传教】
题意很明了,我就不多说了。这道题的难点在于如何累加。由于数据范围很大,所以我们可以先把l,r,k都存下来等到询问的时候再计算。
首先我们先把简单的(传教时的操作)写出来,代码就不放了。
好了,接下来就是计算询问的结果(询问,重点)
如果一段区间在l~r,那么就将其间的所有元素都加上k。由此我们得到式子:
解释:这里还要判断只有一部分重叠的情况,如果两段区间不是完全重合的那就取重合的部分,尾部肯定要取最小,头部肯定要取最大。如果是完全重合这段代码也适用。这里要强制转换成long long。
完整代码:
#include<iostream>
using namespace std;
int n,m,l[1010],r[1010],k[1010],cnt=0,f=0;//l,r,k3个数组是题目中所说的传教的范围和增加的信仰值,cnt是l,r,k3个数组的下标,f是判断是传教还是询问。
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>f;
long long ans=0;//和,记得开long long
if(f==1){//如果是传教
cnt++;
cin>>l[cnt]>>r[cnt]>>k[cnt];//这里不能直接用i,因为f可能是2,就会出错
}else{//如果不是传教,是询问
int lx,rx;//询问区间的头和尾
cin>>lx>>rx;
for(int j=1;j<=cnt;j++){
if(lx<=r[j]&&rx>=l[j]){//如果有重叠
ans+=(long long)k[j]*(min(rx,r[j])-max(lx,l[j])+1);//累加,记得强制转换成long long,不然只有80分
}
}
cout<<ans<<endl;
}
}
return 0;//拜拜!
}