題目連結: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;
}