题解 P2667 【[TJOI2012]防御】
下面的题解管理员可以删了,改题了。
如果对于盾没爆前或者盾都是0的情况,一个线段树就可以了
现在问题是盾可以挡多少伤害(样例中2号1的盾可以挡2伤害)
这个可以直接在线段树上向下搜,因为每个叶子节点最多只会盾爆一次,所以效率是O(nlgn)的
具体操作是维护min,修改的时候区间减(需要lazy),每次找会爆盾的子树,爆盾的min改为maxint就好了
查询就是查路径上的伤害总和*2-盾挡的伤害或者伤害总和(盾没爆)
维护sum,不用下放(不用lazy),查询的时候统计即可
#include<cstdio>
using namespace std;
#define fo(a,b,c) for(int a=b;a<=c;a++)
#define LL long long
int read(){
int a=0,f=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
return f?-a:a;
}
int min(int a,int b){return a<b?a:b;}
const int N=1e5+1,mo=1e9+9;//模数是1e9+9不是1e9+7
LL sum[N<<2],lazy[N<<2],boom[N],d[N],minx[N<<2];
void pushup(int rt){
minx[rt]=min(minx[rt<<1],minx[rt<<1^1]);
}
void pushdown(int rt){
if(minx[rt<<1]!=2e9)minx[rt<<1]-=lazy[rt];
if(minx[rt<<1^1]!=2e9)minx[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){
d[l]=read();
minx[rt]=d[l]?d[l]:2e9;
return;
}
int m=l+r>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1^1);
pushup(rt);
}
void change(int l,int r,int rt,int s){//除了这个函数都是线段树的函数,这个函数就是搜爆盾的函数
if(l==r){d[l]=d[l]-minx[rt]+s;minx[rt]=2e9;boom[l]=1;return;}//记录盾挡的伤害和爆炸标记
int m=l+r>>1;
if(lazy[rt])pushdown(rt);
if(s>=minx[rt<<1])change(l,m,rt<<1,s);
if(s>=minx[rt<<1^1])change(m+1,r,rt<<1^1,s);
pushup(rt);
}
void add(int l,int r,int rt,int L,int R,int c,LL s){
if(L<=l&&r<=R){
sum[rt]+=c;
if(minx[rt]<=c)change(l,r,rt,c);
if(minx[rt]!=2e9)minx[rt]-=c,lazy[rt]+=c;
return;
}
s+=sum[rt];
if(lazy[rt])pushdown(rt);
int m=l+r>>1;
if(L<=m)add(l,m,rt<<1,L,R,c,s);
if(m<R)add(m+1,r,rt<<1^1,L,R,c,s);
pushup(rt);
}
int query(int l,int r,int rt,int p){
if(l==r)return sum[rt]%mo;
int m=l+r>>1;
if(p<=m)return(sum[rt]+query(l,m,rt<<1,p))%mo;
else return(sum[rt]+query(m+1,r,rt<<1^1,p))%mo;
}
int main(){
int n=read(),q=read();LL ans=0;
build(1,n,1);
fo(i,1,q){
scanf("\n");
if(getchar()=='A'){
int L=read(),R=read(),c=read();
add(1,n,1,L,R,c,0);
}
else{
int x=read();
if(boom[x])ans=(ans+query(1,n,1,x)*2-d[x]+mo)%mo;
else ans=(ans+query(1,n,1,x))%mo;
}
}
printf("%lld",ans);
return 0;
}