您的位置:首页 > 其它

【模板】线段树 洛谷 3372 线段树

2017-01-13 19:08 344 查看

题目描述

如题,已知一个数列,你需要进行下面两种操作:

1.将某区间每一个数加上x

2.求出某区间每一个数的和

分析

简单的线段树+lazy标记

复习一下如何写lazy。

code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>

using namespace std;

struct arr{
int x,y;
long long lazy;
long long sum;
}f[3000000];

int n,m;

void delay(int x)//延迟标记。
{
f[x*2].lazy+=f[x].lazy;
f[x*2+1].lazy+=f[x].lazy;
f[x*2].sum+=(f[x*2].y-f[x*2].x+1)*f[x].lazy;
f[x*2+1].sum+=(f[x*2+1].y-f[x*2+1].x+1)*f[x].lazy;
f[x].lazy=0;
}

int insert(int r,int x,int y,int add)//线段树修改操作。
{
delay(r);
f[r].sum+=(y-x+1)*add;
if ((f[r].x==x)&&(f[r].y==y))
{
f[r].lazy+=add;
return 0;
}
int mid=(f[r].x+f[r].y)/2;
if (y<=mid) insert(r*2,x,y,add);
else if (x>mid) insert(r*2+1,x,y,add);
else insert(r*2,x,mid,add),insert(r*2+1,mid+1,y,add);
}

long long find(int r,int x,int y)//线段树查找。
{
delay(r);
if ((f[r].x==x)&&(f[r].y==y)) return f[r].sum;
int mid=(f[r].x+f[r].y)/2;
if (y<=mid) return find(r*2,x,y);
else if (x>mid) return find(r*2+1,x,y);
else return find(r*2,x,mid)+find(r*2+1,mid+1,y);
}

int maketree(int r,int x,int y)//建树
{
f[r].x=x; f[r].y=y;
f[r].lazy=0; f[r].sum=0;
if (x==y) return 0;
int mid=(x+y)/2;
maketree(r*2,x,mid),maketree(r*2+1,mid+1,y);
}

int main()
{
scanf("%d%d",&n,&m);
maketree(1,1,n);
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
insert(1,i,i,x);
}
for (int i=1;i<=m;i++)
{
int l,x,y,w;
scanf("%d",&l);
if (l==1)
{
scanf("%d%d%d",&x,&y,&w);
insert(1,x,y,w);
}
else
{
scanf("%d%d",&x,&y);
printf("%lld\n",find(1,x,y));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: