线段树模板1

来源:互联网 发布:淘宝达人怎么发帖子 编辑:程序博客网 时间:2024/06/05 17:54

最近刚刚开始学线段树,今天终于A掉了区间修改区间求和感人啊(还要打标记!!!!)

题目来源:https://www.luogu.org/problem/show?pid=3372#sub

#include<iostream>

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#define M 500005
using namespace std;
long long e[M];//标记
long long d[M];//和 
long long a[M];
long long b[M];
long long c[M]; 
long long sum1;


void build(int k,int x,int y)
{
b[k]=x;
c[k]=y;
if (x==y){
d[k]=a[x];
return;
}
else {
int mid=(x+y)/2;
build(k*2,x,mid);
build(2*k+1,mid+1,y);
d[k]=d[k*2]+d[k*2+1];
}
}


void mountain(int k)
{
e[k*2]=e[k*2]+e[k];
e[k*2+1]=e[k*2+1]+e[k];
d[k*2]=d[k*2]+e[k]*(c[k*2]-b[k*2]+1);
d[k*2+1]=d[k*2+1]+e[k]*(c[k*2+1]-b[k*2+1]+1);
e[k]=0;
}


void add(int k,int left,int right,int ckr)//[left,right]区间加上ckr 
{
if (right<b[k]||left>c[k]){
return;
}
else{
if (left<=b[k]&&right>=c[k]){
e[k]=e[k]+ckr;
d[k]=d[k]+ckr*(c[k]-b[k]+1);
return;
}
if (e[k]) mountain(k);
add(k*2,left,right,ckr);
add(k*2+1,left,right,ckr);
d[k]=d[k*2]+d[k*2+1];
}
}


long long sum(int left,int right,int k)
{
if (right<b[k]||left>c[k]){
return 0;
}
else {
if (left<=b[k]&&right>=c[k]){
return d[k];
}
if (e[k]){
mountain(k);
}
int mid=(b[k]+c[k])/2;
if (right<=mid){
return sum(left,right,k*2);
}
if (left>mid){
return sum(left,right,k*2+1);
}
if (left<=mid&&right>mid){
return sum(left,mid,k*2)+sum(mid+1,right,k*2+1);
}
}
}
/*void sum(int k,int left,int right)
{
if (right<b[k]||left>c[k]){
return;
}
if (left<=b[k]&&right>c[k]){
sum1=sum1+d[k];
return;
}
if (e[k]) mountain(k);
int mid=(b[k]+c[k])/2;
if (right<=mid){
sum(left,right,k*2);
}
else {
if (left>mid){
sum(left,right,k*2+1);
}
else {
sum(left,mid,k*2);
sum(mid+1,right,k*2+1);
}
}
}*/


int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
for (int i=1;i<=m;i++){
int p;
scanf("%d",&p);
if (p==2){
int x,y,z;
scanf("%d%d",&x,&y);
long long sum1=sum(x,y,1);
printf("%lld\n",sum1);
}
else {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(1,x,y,z);
}
}
return 0;
}
0 0