(lazy标记,区间修改与查询) A - A Simple Problem with Integers
A - A Simple Problem with Integers
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
数据:
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
AC代码:
const int maxn=1e5+5;
ll a[maxn],n,m;
struct Node{
ll l,r,su;
ll lazy;
}tree[maxn<<2+5];
void build(ll l,ll r,ll k)
{
tree[k].su=0;
tree[k].lazy=0;
tree[k].l=l;
tree[k].r=r;
if(l==r){
tree[k].su=a[l];
return ;
}
else{
ll mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
tree[k].su=tree[k<<1].su+tree[k<<1|1].su;
}
}
void down(int k)//k节点lazy标记下传一位
{
if(tree[k].l==tree[k].r) {
//叶子节点
//tree[k].su+=tree[k].lazy;
return ;
}
tree[k<<1].su+=((tree[k<<1].r-tree[k<<1].l+1)*tree[k].lazy);
tree[k<<1].lazy+=tree[k].lazy;
tree[k<<1|1].su+=((tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].lazy);
tree[k<<1|1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
void update(ll l,ll r,ll k,ll p)//区间修改
{
if(tree[k].l>=l && tree[k].r<=r)//不再往下走,lazy标记
{//lazy表示改点以下的节点还未修改
tree[k].su+=((tree[k].r-tree[k].l+1)*p);
tree[k].lazy+=p;
return ;
}
//如果节点区间未被全包含,lazy下传
if(tree[k].lazy) down(k);
ll mid=((tree[k].l+tree[k].r)>>1);
if(l<=mid) update(l,r,k<<1,p);
if(r>mid) update(l,r,k<<1|1,p);
tree[k].su=tree[k<<1].su+tree[k<<1|1].su;
}
ll sum=0;//存区间和
void summ(ll l,ll r,ll k)//区间和
{
if(tree[k].l>=l && tree[k].r<=r)
{
sum+=tree[k].su;
return ;
}
if(tree[k].lazy) down(k);
ll mid=((tree[k].l+tree[k].r)>>1);
if(l<=mid)
summ(l,r,k<<1);
if(r>mid)
summ(l,r,k<<1|1);
}
/*
void add(ll n,ll x,ll k)//单点修改
{
if(tree[k].l<=n && n<=tree[k].r)
{
tree[k].su+=x;
if(!(tree[k].l==tree[k].r))
{
ll mid=(tree[k].l+tree[k].r)>>1;
add(n,x,k<<1);
add(n,x,k<<1|1);
}
}
}
*/
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++) scanf("%lld",a+i);
//for(ll i=1;i<=n;i++) scanf("%lld",x),add());//原先代码(超时)
build(1,n,1);
char s;
while(m--)
{
getchar();
scanf("%c",&s);
ll a,b,c;
if(s=='Q')
{
scanf("%lld%lld",&a,&b);
sum=0;
summ(a,b,1);
printf("%lld\n",sum);
}
else{
scanf("%lld%lld%lld",&a,&b,&c);
update(a,b,1,c);
}
}
return 0;
}
->:一直超时,只要去掉单点修改,在build时就将初始数据加入线段树
还有读数别用cin...
void build(ll l,ll r,ll k)
{
tree[k].su=0;
tree[k].lazy=0;
tree[k].l=l;
tree[k].r=r;
if(l==r){
tree[k].su=a[l];//
return ;
}
else{
ll mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
tree[k].su=tree[k<<1].su+tree[k<<1|1].su;//省去单点修改
}
}

浙公网安备 33010602011771号