线段树专题
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\n",q(y,z,1,n,1));
if(s[0]=='m')u=re(),d(y,z,u,1,n,1);
}
}
紫fhlaudhtaskhfkldjasyrue
ほらあなたの描くこの世界は私を映しているよ----
看呐 你所描绘出的这个世界里,映出了我的身影哟

浙公网安备 33010602011771号