华师一附中OI组
标题:
P3372 【模板】线段树 1
[打印本页]
作者:
admin
时间:
2018-5-13 01:09
标题:
P3372 【模板】线段树 1
题目描述
如题,已知一个数列,你需要进行下面两种操作:
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的结果。
输入输出样例
输入样例#1:
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出样例#1:
11
8
20
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^,保证在int64/long long数据范围内)
样例说明:
作者:
吴语林
时间:
2018-7-29 19:35
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N = 2e5 + 10;
typedef long long LL;
LL sum[N * 4]= {0}, tag[N * 4]= {0},a[N];
void build(int l, int r, int o)
{
if(l == r)
{
sum[o] = a[l];
tag[o] = 0;
return ;
}
int mid = (l + r) >> 1;
build(l, mid, o * 2);
build(mid + 1, r, o << 1 | 1);
sum[o] = sum[o << 1] + sum[o << 1 | 1];
tag[o] = 0;
return ;
}
void update(int L, int R, LL add, int l, int r, int o)
{
if(L <= l && r <= R)
{
sum[o] += (r - l + 1) * add;
tag[o] += add;
return ;
}
int mid = (l + r) >> 1;
if(tag[o])
{
sum[o << 1] += tag[o] * (mid - l + 1);
tag[o << 1] += tag[o];
sum[o << 1|1] += tag[o] * (r - mid);
tag[o << 1|1] += tag[o];
tag[o] = 0;
}
if(L <= mid) update(L, R, add, l, mid, o << 1);
if(R > mid) update(L, R, add, mid + 1, r, o << 1 | 1);
sum[o] = sum[o << 1] + sum[o << 1 | 1];
}
LL query(int L, int R, int l, int r, int o)
{
if(L <= l && r <= R)
{
return sum[o];
}
int mid = (l + r) >> 1;
if(tag[o])
{
sum[o << 1] += tag[o] * (mid - l + 1);
tag[o << 1] += tag[o];
sum[o << 1|1] += tag[o] * (r - mid);
tag[o << 1|1] += tag[o];
tag[o] = 0;
}
LL ans = 0;
if(L <= mid) ans += query(L, R, l, mid, o << 1);
if(R > mid) ans += query(L, R, mid + 1, r, o << 1 | 1);
return ans;
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
for(int i=1; i<=n; i++)
scanf("%lld", &a[i]);
build(1, n, 1);
while(m --)
{
int op;
scanf("%d", &op);
if(op == 1)
{
int l, r;
LL x;
scanf("%d %d %lld", &l, &r, &x);
update(l, r, x, 1, n, 1);
}
else
{
int l, r;
scanf("%d %d", &l, &r);
printf("%lld\n", query(l, r, 1, n, 1));
}
}
}
复制代码
作者:
ZMQ
时间:
2018-8-16 21:57
提示:
作者被禁止或删除 内容自动屏蔽
作者:
admin
时间:
2018-8-17 08:50
zmq同学好厉害呀!
作者:
倚窗倾听风吹雨
时间:
2018-10-4 13:47
#include<iostream>
#define FOR(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
typedef long long int ll;
const int N=100005;
int L,R,m,n;
ll a[N],sum[N<<2],add[N<<2],ans,ad,k;
inline void PushUp(int l,int r,int p){sum[p]=sum[p<<1]+sum[(p<<1)|1]+add[p]*(r-l+1);}
void BuildTree(int l,int r,int p)
{
if(l==r){sum[p]=a[l];return;}
int mid=l+((r-l)>>1),ls=p<<1,rs=p<<1|1;
BuildTree(l,mid,ls);
BuildTree(mid+1,r,rs);
PushUp(l,r,p);return;
}
void Add(int l,int r,int p)
{
if(L<=l && r<=R){sum[p]+=k*(r-l+1);add[p]+=k;return;}
int mid=l+((r-l)>>1),ls=p<<1,rs=p<<1|1;
if(L<=mid) Add(l,mid,ls);
if(R>mid) Add(mid+1,r,rs);
PushUp(l,r,p);return;
}
void query(int l,int r,int p)
{
if(L<=l && r<=R){ans+=sum[p]+ad*(r-l+1);return;}
int mid=l+((r-l)>>1),ls=p<<1,rs=p<<1|1;
ad+=add[p];
if(L<=mid)query(l,mid,ls);
if(R>mid)query(mid+1,r,rs);
ad-=add[p];return;
}
void print(int l,int r,int p)
{
cout<<l<<" "<<r<<" "<<p<<" "<<sum[p]<<" "<<add[p]<<endl;
if(l==r)return;
int mid=l+((r-l)>>1),ls=p<<1,rs=p<<1|1;
print(l,mid,ls);
print(mid+1,r,rs);
}
int main()
{
cin>>n>>m;
FOR(i,1,n)cin>>a[i];
BuildTree(1,n,1);
while(m--)
{
int x;
cin>>x>>L>>R;
if(x==1)
{
cin>>k;
Add(1,n,1);
/// print(1,n,1);
/// cout<<"---------------"<<endl;
}
else
{
ans=0;ad=0;
query(1,n,1);
cout<<ans<<endl;
}
}
return 0;
}
复制代码
作者:
admin
时间:
2020-5-4 12:46
基本线段树
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2