Ayaya......好久没发博客了呢(笑..这几天大概算做了线段树的专题吧,以前的题里其实也有能用线段树吧,
但都没有去写,终于集中练了一下线段树。。总体来说线段树还是很好理解的,只是代码稍长了点,多用一用
背熟了就好了。
这次专题是在COGS上练习的,其中有几道模板题,过了大概以后就能用了:
单点修改区间查询:COGS 264 http://www.cogs.pro/cogs/problem/problem.php?pid=264
区间修改单点查询:COGS 1316 http://www.cogs.pro/cogs/problem/problem.php?pid=1316
区间修改区间查询:COGS 1317 http://www.cogs.pro/cogs/problem/problem.php?pid=1317
下面附上线段树区间修改区间查询的代码
#include<cstdio> #define ll long long using namespace std; ll n,m,y,u,z,tr[20010],la[20010]; char s[10]; ll re() { ll x=0,c=getchar(),f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void t(ll x,ll y,ll r) { if(x==y) { tr[r]=re(); return; } ll mid=(x+y)>>1; t(x,mid,r<<1); t(mid+1,y,(r<<1)+1); tr[r]=tr[r<<1]+tr[(r<<1)+1]; } void down(ll rt,ll ln,ll rn){ if(la[rt]){ la[rt<<1]+=la[rt]; la[rt<<1|1]+=la[rt]; tr[rt<<1]+=la[rt]*ln; tr[rt<<1|1]+=la[rt]*rn; la[rt]=0; } } void d(ll x,ll b,ll y,ll r,ll u,ll l) { if(x<=r&&u<=b) { tr[l]+=y*(u-r+1); la[l]+=y; return; } ll mid=(r+u)>>1; down(l,mid-r+1,u-mid); if(x<=mid)d(x,b,y,r,mid,l<<1); if(b>mid)d(x,b,y,mid+1,u,(l<<1)+1); tr[l]=tr[l<<1]+tr[(l<<1)+1]; } ll q(ll x,ll y,ll r,ll u,ll l) { if(x<=r&&y>=u)return tr[l]; ll mid=(r+u)>>1,he=0; down(l,mid-r+1,u-mid); if(x<=mid)he+=q(x,y,r,mid,l<<1); if(y>mid)he+=q(x,y,mid+1,u,(l<<1)+1); return he; } int main() { //freopen("shuliec.in","r",stdin);freopen("shuliec.out","w",stdout); n=re();m=re(); if(n==0)return 0; t(1,n,1); while(m--) { scanf("%s",&s);y=re();z=re(); if(s[0]=='q')printf("%lld ",q(y,z,1,n,1)); if(s[0]=='m')u=re(),d(y,z,u,1,n,1); } }
紫fhlaudhtaskhfkldjasyrue