UESTC 1073 秋实大哥与线段树 (线段树)
“学习本无底,前进莫徬徨。” 秋实大哥对一旁玩手机的学弟说道。
秋实大哥是一个爱学习的人,今天他刚刚学习了线段树这个数据结构。
为了检验自己的掌握程度,秋实大哥给自己出了一个题,同时邀请大家一起来作。
秋实大哥的题目要求你维护一个序列,支持两种操作:一种是修改某一个元素的值;一种是询问一段区间的和。
Input
第一行包含一个整数nn,表示序列的长度。
接下来一行包含nn个整数aiai,表示序列初始的元素。
接下来一行包含一个整数mm,表示操作数。
接下来mm行,每行是以下两种操作之一:
1 x v : 表示将第x个元素的值改为v
2 l r : 表示询问[l,r]这个区间的元素和
1≤n,m,v,ai≤1000001≤n,m,v,ai≤100000,1≤l≤r≤n1≤l≤r≤n。
Output
对于每一个22 ll rr操作,输出一个整数占一行,表示对应的答案。
Sample Input
3 1 2 3 3 2 1 2 1 1 5 2 1 2
Sample Output
3 7
题解:
这是一道线段树的裸题。
#include<iostream> #include<cstdio> #include<algorithm> #include<string> #include<cmath> #include<set> #include<map> using namespace std; typedef long long LL; inline LL read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=1e5+5; struct Node { int l,r; LL sum; }seg[maxn<<2]; int num[maxn]; void push_up(int n) { seg[n].sum=seg[n<<1].sum+seg[n<<1|1].sum; } void build(int i,int l,int r) { seg[i].l=l; seg[i].r=r; if(l==r) { seg[i].sum=num[l]; return ; } int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); push_up(i); } void updata(int i,int t,int val) { if(seg[i].l==t&&seg[i].r==t) { seg[i].sum=val; return ; } int mid=(seg[i].l+seg[i].r)>>1; if(t<=mid) updata(i<<1,t,val); else updata(i<<1|1,t,val); push_up(i); } LL query(int i,int l,int r) { if(seg[i].l>=l&&seg[i].r<=r) return seg[i].sum; int mid=(seg[i].l+seg[i].r)>>1; if(r<=mid) return query(i<<1,l,r); if(l>mid) return query(i<<1|1,l,r); return query(i<<1,l,mid)+query(i<<1|1,mid+1,r); } int main() { ios::sync_with_stdio(false); int n; cin>>n; for(int i=1;i<=n;i++) cin>>num[i]; build(1,1,n); int t; cin>>t; while(t--) { int q,a,b; cin>>q>>a>>b; if(q==1) updata(1,a,b); else cout<<query(1,a,b)<<endl; } return 0; }