您的位置:首页 > 其它

<线段树系列2> codevs 1082 线段树练习2

2017-08-13 18:12 399 查看
还是一道很简单的线段树模板

codevs 1082 线段树练习2

题目描述 Description

给你N个数,有两种操作

1:给区间[a,b]的所有数都增加X

2:询问第i个数是什么?

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 3

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

1<=n<=100000

1<=q<=100000

一句话:单点查询,区间修改

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;

const int maxn=1e5+5;
int n,q;
int a[maxn];
struct hh
{
int l,r;
int summ,add;
}tree[maxn<<2];

void Updata(int i,int x)
{
tree[i].summ+=x*(tree[i].r-tree[i].l+1);
}
void Spread(int i)
{
int &xa=tree[i].add;
if(xa)
{
tree[i<<1].add+=xa;
tree[i<<1|1].add+=xa;
Updata(i<<1,xa);
Updata(i<<1|1,xa);
xa=0;
}
}
void Add(int l,int r,int x,int i)
{
int lx=tree[i].l;
int rx=tree[i].r;
if(lx>=l&&rx<=r)
{
tree[i].add+=x;
Updata(i,x);
return;
}
Spread(i);
int mid=(lx+rx)>>1;
if(l<=mid) Add(l,r,x,i<<1);
if(r>mid) Add(l,r,x,i<<1|1);
tree[i].summ=tree[i<<1].summ+tree[i<<1|1].summ;
}
int Ask(int x,int i)
{
if(tree[i].l==tree[i].r) return tree[i].summ;
Spread(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(x<=mid) return Ask(x,i<<1);
if(x>mid) return Ask(x,i<<1|1);
}
int Build(int l,int r,int i)
{
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].summ=a[l];
return a[l];
}
int mid=(r+l)>>1;
return tree[i].summ=Build(l,mid,i<<1)+Build(mid+1,r,i<<1|1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
Build(1,n,1);
scanf("%d",&q);
for(int i=1;i<=q;++i)
{
int ques;
scanf("%d",&ques);
if(ques==1)
{
int a,b,x;
scanf("%d%d%d",&a,&b,&x);
Add(a,b,x,1);
}
else
{
int love;
scanf("%d",&love);
printf("%d\n",Ask(love,1));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: