2022江西省賽K Peach Conference

Captainfly19發表於2024-06-02

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

相關文章