华师一附中OI组
标题:
P3372 【模板】线段树1
[打印本页]
作者:
liubo
时间:
2018-7-29 19:03
标题:
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:
[url=]复制[/url]5 51 5 4 2 32 2 41 2 3 22 3 41 1 5 12 1 4
输出样例#1:
[url=]复制[/url]11820
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^,保证在int64/long long数据范围内)
样例说明:
作者:
liubo
时间:
2018-7-29 19:04
#include<iostream>
using namespace std;
struct node{
int l,r;
long long sum;
long long inc;
int mid(){
return (l + r)/2;
}
}t[300010];
void buildTree(int root,int l,int r){
node &n = t[root];
n.l = l;
n.r = r;
n.sum = 0;
n.inc = 0;
/**!!!**/if(l == r) return;
buildTree(root * 2 + 1,l,n.mid());
buildTree(root * 2 + 2,n.mid() + 1,r);
}
void insertNum(int root,int i,int v){
node &n = t[root];
if(n.l == n.r && n.l == i){
n.sum = v;
return;
}
n.sum += v;
if(i > n.mid())
insertNum(root * 2 + 2,i,v);
else
insertNum(root * 2 + 1,i,v);
}
void addNum(int root,int l,int r,int v){
node &n = t[root];
if(n.l == l && n.r == r){
n.inc += v;
return;
}
//n.inc += v;
n.sum += v * (r - l + 1);
if(l > n.mid())
addNum(root * 2 + 2,l,r,v);
else if(r <= n.mid())
addNum(root * 2 + 1,l,r,v);
else{
addNum(root * 2 + 1,l,n.mid(),v);
addNum(root * 2 + 2,n.mid() + 1,r,v);
}
}
long long askSum(int root,int l,int r){
node &n = t[root];
if(n.l == l && n.r == r)
return n.sum + (r - l + 1) * n.inc;
n.sum += (n.r - n.l + 1) * n.inc;
addNum(root * 2 + 1,n.l,n.mid(),n.inc);
addNum(root * 2 + 2,n.mid() + 1,n.r,n.inc);
n.inc = 0;
if(l > n.mid())
return askSum(root * 2 + 2,l,r);
else if(r <= n.mid())
return askSum(root * 2 + 1,l,r);
else{
return askSum(root * 2 + 1,l,n.mid()) +
askSum(root * 2 + 2,n.mid() + 1,r);
}
}
int main(){
int n,m,c,l,r,v,k;
cin >> n >> m;
buildTree(0,1,n);
for(int i = 1;i <= n;i++){
cin >> k;
insertNum(0,i,k);
}
for(int i = 1;i <= m;i++){
cin >> c;
if(c == 1){
cin >> l >> r >> k;
addNum(0,l,r,k);
}else{
cin >> l >> r;
cout << askSum(0,l,r) << endl;
}
}
return 0;
}
复制代码
作者:
吴语林
时间:
2018-7-29 19:30
#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));
}
}
}
复制代码
作者:
walk_alone
时间:
2018-7-29 20:13
#include <cstdio>
long long a[1000001],sum[4000001],tag[4000001];
void build(long long place,long long left,long long right)
{
if(left==right)
{
sum[place]=a[left];
return;
}
long long mid=(left+right)>>1;
build(place<<1,left,mid);
build(place<<1|1,mid+1,right);
sum[place]=sum[place<<1]+sum[place<<1|1];
}
inline void find(long long left,long long right,long long place,long long x)
{
tag[place]+=x;
sum[place]+=x*(right-left+1);
}
inline void putdown(long long left,long long right,long long place)
{
long long mid=(left+right)>>1;
find(left,mid,place<<1,tag[place]);
find(mid+1,right,place<<1|1,tag[place]);
tag[place]=0;
}
inline void change(long long start,long long end,long long left,long long right,long long place,long long x)
{
if(start<=left && right<=end)
{
tag[place]+=x;
sum[place]+=x*(right-left+1);
return;
}
putdown(left,right,place);
long long mid=(left+right)>>1;
if(start<=mid)
change(start,end,left,mid,place<<1,x);
if(end>mid)
change(start,end,mid+1,right,place<<1|1,x);
sum[place]=sum[place<<1|1]+sum[place<<1];
}
long long query(long long start,long long end,long long left,long long right,long long place)
{
long long ans=0;
if(start<=left && right<=end)
return ans=sum[place];
long long mid=(left+right)>>1;
putdown(left,right,place);
if(start<=mid)
ans+=query(start,end,left,mid,place<<1);
if(end>mid)
ans+=query(start,end,mid+1,right,place<<1|1);
return ans;
}
int main()
{
long long n,m,p,q,x;
int k;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&k);
if(k==1)
{
scanf("%lld%lld%lld",&p,&q,&x);
change(p,q,1,n,1,x);
}
if(k==2)
{
scanf("%lld%lld",&p,&q);
printf("%lld\n",query(p,q,1,n,1));
}
}
return 0;
}
复制代码
作者:
zhwang
时间:
2018-7-30 08:31
#include<cstdio>
#define int long long
int a[100001];
int he;
int n,m,k,l,r,x;
struct node
{
int left;
int right;
int sum;
int tag;
}tree[400001];
void setup(int root,int start,int end)
{
tree[root].tag=0;
tree[root].left=start;
tree[root].right=end;
if(start==end)
{
tree[root].sum=a[start];
}
else
{
setup(root*2,start,start+(end-start)/2);
setup(root*2+1,start+(end-start)/2+1,end);
tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
}
}
void add(int start,int end,int root,int num)
{
if(tree[root].left==start&&tree[root].right==end)
{
tree[root].tag+=num;
return;
}
else
{
if(end<=tree[root*2].right)
{
add(start,end,2*root,num);
}
else
{
if(start>=tree[root*2+1].left)
{
add(start,end,2*root+1,num);
}
else
{
add(start,tree[2*root].right,2*root,num);
add(tree[2*root+1].left,end,2*root+1,num);
}
}
}
tree[2*root].tag+=tree[root].tag;
tree[2*root+1].tag+=tree[root].tag;
tree[root].tag=0;
tree[root].sum=tree[2*root].sum+tree[2*root+1].sum+tree[2*root].tag*(tree[2*root].right-tree[2*root].left+1)+tree[2*root+1].tag*(tree[2*root+1].right-tree[2*root+1].left+1);
}
long long findout(int start,int end,int root)
{
if (tree[root].left==start&&tree[root].right==end)
{
return tree[root].sum+tree[root].tag*(end-start+1);
}
long long answer=0;
tree[2*root].tag+=tree[root].tag;
tree[2*root+1].tag+=tree[root].tag;
tree[root].tag=0;
tree[root].sum=tree[2*root].sum+tree[2*root+1].sum+tree[2*root].tag*(tree[2*root].right-tree[2*root].left+1)+tree[2*root+1].tag*(tree[2*root+1].right-tree[2*root+1].left+1);
if(start>=tree[root*2+1].left)
{
answer=findout(start,end,root*2+1);
}
else
{
if(end<=tree[root*2].right)
{
answer=findout(start,end,root*2);
}
else
{
answer+=findout(start,tree[root*2].right,root*2);
answer+=findout(tree[root*2+1].left,end,root*2+1);
}
}
return answer;
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
setup(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%lld",&k);
if(k==1)
{
scanf("%lld%lld%lld",&l,&r,&x);
add(l,r,1,x);
}
else
{
if(k==2)
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",findout(l,r,1));
}
}
}
return 0;
}
复制代码
作者:
倚窗倾听风吹雨
时间:
2018-10-4 13:49
#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;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2