您的位置:首页 > 其它

洛谷P3372 线段树1【模板】

2017-12-26 23:11 399 查看

题目

题目描述

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

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

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

输入输出格式

输入格式:

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

输出格式:

输出包含若干行整数,即为所有操作2的结果。

输入输出样例

输入

5 5

1 5 4 2 3

2 2 4

1 2 3 2

2 3 4

1 1 5 1

2 1 4

输出

11

8

20

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000

分析

翻译过来就是:给你一颗线段树,区间修改或区间查询。
lazy标记法。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <vector>
#include <cstdlib>
#include <ctime>
//日常头文件
using namespace std;
//依然头文件
typedef long long ll;
//懒得打
const int N=100900;
//数据范围
ll ans;
//可能很大
ll a
;
//可能很大
struct node
{
ll sum;
ll addv;
};

node v[N*4];

void Add(ll,ll,ll,ll);
//操作2第二步
void pushdown(ll,ll,ll);
//向下
void pushup(ll);
//向上
void buitre(ll,ll,ll);
//建树
ll Query(ll,ll,ll,ll,ll);
//区间查询
void update(ll,ll,ll,ll,ll,ll);
//区间修改
int main()
{
int n;
int m;

scanf("%d",&n);
scanf("%d",&m);

for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
//以上不解释
buitre(1,n,1);
//建树
for(int i=1;i<=m;i++)
{
int opt;

scanf("%d",&opt);

if(opt==1)
{
int x;
int y;
int k;

scanf("%d",&x);
scanf("%d",&y);
scanf("%d",&k);

update(x,y,k,1,n,1);
}
else//我不信还有第三个操作嘎哈哈
{
int x;
int y;

scanf("%d",&x);
scanf("%d",&y);

ll answ;

answ=Query(x,y,1,n,1);

printf("%lld\n",answ);
}
//分开写是因为读入的数的个数不一样
//也可以强制性写一起
}
//处理操作
return 0;
}

void Add(ll l,ll r,ll C,ll rt)
{
v[rt].sum+=(r-l+1)*C;

v[rt].addv+=C;
}

void pushdown(ll l,ll r,ll rt)
{
ll mid;

mid=(l+r)/2;

if(v[rt].addv)
{
ll C;

C=v[rt].addv;

Add(l,mid,C,rt<<1);
Add(mid+1,r,C,rt<<1|1);

v[rt].addv=0;
}
}

void pushup(ll rt)
{
v[rt].sum=v[rt*2].sum+v[rt*2+1].sum;
}

void buitre(ll l,ll r,ll rt)
{
if(l==r)
{
v[rt].sum=a[l];

return;
}
ll mid;
mid=(l+r)/2;

buitre(l,mid,2*rt);
buitre(mid+1,r,2*rt+1);

pushup(rt);
}

ll Query(ll L,ll R,ll l,ll r,ll rt)
{
if(L<=l&&r<=R)
return v[rt].sum;
ll mid;
ll ans;

mid=(l+r)>>1;
ans=0;

pushdown(l,r,rt);

if(L<=mid)
ans+=Query(L,R,l,mid,rt<<1);

if(R>mid)
ans+=Query(L,R,mid+1,r,rt<<1|1);

return ans;
}

void update(ll L,ll R,ll C,ll l,ll r,ll rt)
{
if(L<=l&&r<=R)
{
Add(l,r,C,rt);

return;
}

ll mid;

mid=(l+r)>>1;

pushdown(l,r,rt);

if(L<=mid)
update(L,R,C,l,mid,rt<<1);

if(R>mid)
update(L,R,C,mid+1,r,rt<<1|1);

pushup(rt);
}
//哦,好长
//妈呀终于完事了
调了半天我去
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: