2022江西省赛K Peach Conference
题目链接:https://ac.nowcoder.com/acm/contest/43898/K
大致做法:
只需要会线段树打懒标记和维护最大最小值,再对线段树懒标记下传操作有一些比较深入的理解即可做本题.1、3操作是简单的区间加和区间求和,没什么问题,主要是2操作.
我们来理解一下2操作对应的性质.我们可以想到一个暴力的做法:对于线段树的每一层一层层递归下去,直到递归到最后一层,也就是只包含一个数的区间,再和 |m| 比较大小并做出相应的更改.但是这样做和暴力跑无本质区别.
我们考虑优化.
那么对于当前遍历的区间假如区间最大值都比 |m| 小的话,那么我们直接打懒标记把当前区间全部修改成0即可.如果当前遍历区间最小值都比 |m| 大的话,那么就只做区间减即可.
#define int long long
#define maxn 200010
int n,q;
struct node{
int l,r;
int val,addtag;
int maxx,minn;
int clear;
}seg[maxn<<2];
void pushup(int rt)
{
seg[rt].val=seg[lson].val+seg[rson].val;
seg[rt].maxx=max(seg[lson].maxx,seg[rson].maxx);
seg[rt].minn=min(seg[lson].minn,seg[rson].minn);
}
void pushdown(int rt)
{
if(seg[rt].clear)
{
seg[lson].val=seg[lson].minn=seg[lson].maxx=seg[lson].addtag=0;
seg[lson].clear=1;
seg[rson].val=seg[rson].minn=seg[rson].maxx=seg[rson].addtag=0;
seg[rson].clear=1;
seg[rt].clear=0;
}
if(seg[rt].addtag)
{
seg[lson].val+=seg[rt].addtag*(seg[lson].r-seg[lson].l+1);
seg[rson].val+=seg[rt].addtag*(seg[rson].r-seg[rson].l+1);
seg[lson].maxx+=seg[rt].addtag;
seg[rson].maxx+=seg[rt].addtag;
seg[lson].minn+=seg[rt].addtag;
seg[rson].minn+=seg[rt].addtag;
seg[lson].addtag+=seg[rt].addtag;
seg[rson].addtag+=seg[rt].addtag;
seg[rt].addtag=0;
}
}
void build(int rt,int l,int r)
{
seg[rt].l=l;
seg[rt].r=r;
if(l==r)
{
return ;
}
int mid = (l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
void change(int rt,int x,int y,int val)
{
int l=seg[rt].l;
int r=seg[rt].r;
if(x<=l&&r<=y)
{
if(seg[rt].minn+val>=0)
{
seg[rt].maxx+=val;
seg[rt].minn+=val;
seg[rt].val+=val*(seg[rt].r-seg[rt].l+1);
seg[rt].addtag+=val;
return ;
}
if(seg[rt].maxx+val<=0)
{
seg[rt].val=seg[rt].maxx=seg[rt].minn=seg[rt].addtag=0;
seg[rt].clear=1;
return ;
}
}
pushdown(rt);
int mid = (l+r)>>1;
if(x<=mid)change(lson,x,y,val);
if(y>mid) change(rson,x,y,val);
pushup(rt);
}
int query(int rt,int x,int y)
{
int l=seg[rt].l;
int r=seg[rt].r;
if(x<=l&&r<=y)
{
return seg[rt].val;
}
int mid = (l+r)>>1;
pushdown(rt);
int ans=0;
if(x<=mid) ans+=query(lson,x,y);
if(y>mid) ans+=query(rson,x,y);
return ans;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
build(1,1,n);
while(q--)
{
int op,l,r;
cin>>op>>l>>r;
if(op==0)
{
cout<<query(1,l,r)<<'\n';
}
else
{
change(1,l,r,op);
}
}
return 0;
}