题目大意:给定一个区间,有三种操作,第一种是把第i个元素的值清空,第二个是往第i个元素中加上v的值,第三种是询问第区间[i,j]中的总和是多少;
题目解析:线段树,清空操作设置一个标记就可以了,update的时候直接输出;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int val[400010],lazy[400010];
void pushup(int rt)
{
val[rt]=val[rt<<1]+val[rt<<1|1];
}
void pushdown(int rt)
{
if(lazy[rt]==0) return ;
val[rt<<1]+=lazy[rt];
val[rt<<1|1]+=lazy[rt];
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%d",&val[rt]);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
int query(int le,int ri,int l,int r,int rt)
{
if(le<=l&&ri>=r)
{
return val[rt];
}
pushdown(rt);
int m=(l+r)>>1,ans=0;
if(le<=m) ans+=query(le,ri,lson);
if(ri>m) ans+=query(le,ri,rson);
return ans;
}
void update(int le,int ri,int mon,int l,int r,int rt)
{
if(le<=l&&ri>=r)
{
if(mon==-1)
{
printf("%d\n",val[rt]);
val[rt]=0;
return ;
}
else
{
val[rt]+=mon;
lazy[rt]+=mon;
return ;
}
}
pushdown(rt);
int m=(l+r)>>1;
if(le<=m) update(le,ri,mon,lson);
if(ri>m) update(le,ri,mon,rson);
pushup(rt);
}
int main()
{
int cas,c,n,m;
scanf("%d",&cas);
for(c=1;c<=cas;c++)
{
memset(val,0,sizeof(val));
memset(lazy,0,sizeof(lazy));
scanf("%d%d",&n,&m);
printf("Case %d:\n",c);
build(1,n,1);
while(m--)
{
int ch;
scanf("%d",&ch);
if(ch==1)
{
int pos;
scanf("%d",&pos);
pos++;
update(pos,pos,-1,1,n,1);
}
else if(ch==2)
{
int v,x;
scanf("%d%d",&x,&v);
x++;
update(x,x,v,1,n,1);
}
else
{
int st,la;
scanf("%d%d",&st,&la);
st++;
la++;
printf("%d\n",query(st,la,1,n,1));
}
}
}
return 0;
}