\(\mathcal{6.}\)
$\ \ \ \ \ \ \ $CTH 自己知道不能和他们谈天,便只好向孩子说话。
$\ \ \ \ \ \ \ $有一回对我说道,“你写过程序么?”
$\ \ \ \ \ \ \ $我略略点一点头。
$\ \ \ \ \ \ \ $他说,“写过,……我便考你一考。数据结构里的线段树,怎样在实现单点修改和区间求和?”
$\ \ \ \ \ \ \ $我想,讨饭一样的人,也配考我么?便回过脸去,不再理会。
$\ \ \ \ \ \ \ $ CTH 等了许久,很恳切的说道,“不会罢?……我教给你,记着!这些模板应该记着。将来做教练的时候,混饭要用。”
$\ \ \ \ \ \ \ $我暗想我和教练的等级还很远呢,而且我们教练也从不讲线段树;又好笑,又不耐烦,懒懒的答他道,“谁要你教,不就是线段树将每个长度不为 1 的区间划分成左右两个区间递归求解吗?”
$\ \ \ \ \ \ \ $ CTH 显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说,“对呀对呀!……线段树有四样写法,你知道么?包括线段树,可持久化线段树,动态开点,以及标记永久化。你的这个办法不好,有很多冗余,万一有人写错了,也不好追查责任,我写给你看,你看我的代码,优美极了”:
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int MAX=1e5+10;
int a[MAX];
struct node{int l,r,max,sum;
}tree[MAX<<2];
int lson(int x)
{return x << 1;
}
int rson(int x)
{return x<<1|1;
}
void build(int rt,int l,int r)
{tree[rt].l=l;tree[rt].r=r;if(l==r){tree[rt].sum=tree[rt].max=a[l];return;}int mid=(l+r)>>1;build(lson(rt),l,mid);build(rson(rt),mid+1,r);tree[rt].sum=tree[lson(rt)].sum+tree[rson(rt)].sum;tree[rt].max=max(tree[lson(rt)].max,tree[rson(rt)].max);
}
void update(int rt,int pos,int v)
{//cout<<'#';if(tree[rt].l==tree[rt].r){tree[rt].sum=tree[rt].max=v;return ;}int mid=(tree[rt].l+tree[rt].r)>>1;if(pos<=mid) update(lson(rt),pos,v);else update(rson(rt),pos,v);tree[rt].sum=tree[lson(rt)].sum+tree[rson(rt)].sum;tree[rt].max=max(tree[lson(rt)].max,tree[rson(rt)].max);
}
int query(int rt,int l,int r)
{if(l<=tree[rt].l&&tree[rt].r<=r) return tree[rt].sum;int mid=(tree[rt].l+tree[rt].r)>>1;if(r<=mid) return query(lson(rt),l,r);else if(l>mid) return query(rson(rt),l,r);else return (query(lson(rt),l,r)+query(rson(rt),l,r));
}
int main()
{cin>>n;if(n==0) {//cout<<0;return 0;}for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);cin>>m;string s;for(int i=1;i<=m;i++){//for(int i=1;i<=n;i++)cin>>s;if(s[0]=='S'){int x,y;cin>>x>>y;cout<<query(1,x,y)<<endl;}else{int x,y;cin>>x>>y;update(1,x,y+a[x]);a[x]=y+a[x];}}
}
$\ \ \ \ \ \ \ $我愈不耐烦了,努着嘴走远。写完后,CTH 向教练讨来一副模板,还想继续说些什么,见我毫不热心,便又叹一口气,显出极惋惜的样子。
\(\mathcal{7.}\)
CTH 是这样的使人快活,可是没有他,别人也便这么过。