[P4145] 花神游历各国 - 线段树

Description

维护序列,支持区间开方下取整,区间求和。

Solution

对线段树上的每个 Node 记录最大值 \(mx\)

修改操作时,若当前结点 \(mx=1\) 则不用继续修改

(代码里有很多冗余的东西请手动忽略)

#include <bits/stdc++.h>
using namespace std;

#define int long long

#define lc p*2,l,(l+r)/2
#define rc p*2+1,(l+r)/2+1,r
#define NULLNODE {-1e18,1e18,0}

const int N = 400005;

int n,m,a[N],t1,t2,t3;

struct Node
{
    int mx,mn,sum;
    Node operator + (const Node &b) const
    {
        Node res;
        res.mn=min(mn,b.mn);
        res.mx=max(mx,b.mx);
        res.sum=sum+b.sum;
        return res;
    }
    bool ok()
    {
        return mx==1 || sum==mx;
    }
    void set(int x,int len)
    {
        mx=mn=x;
        sum=len*x;
    }
};

Node node[N];

void build(int p,int l,int r)
{
    if(l==r)
    {
        node[p].set(a[l],1);
    }
    else
    {
        build(lc);
        build(rc);
        node[p]=node[p*2]+node[p*2+1];
    }
}

void modify(int p,int l,int r,int ql,int qr)
{
    if(l>qr||r<ql) return;
    if(l>=ql&&r<=qr&&node[p].ok())
    {
        node[p].set(sqrt(node[p].mx+0.1),r-l+1);
    }
    else
    {
        modify(lc,ql,qr);
        modify(rc,ql,qr);
        node[p]=node[p*2]+node[p*2+1];
    }
}

Node query(int p,int l,int r,int ql,int qr)
{
    if(l>qr||r<ql) return NULLNODE;
    if(l>=ql&&r<=qr) return node[p];
    return query(lc,ql,qr)+query(rc,ql,qr);
}

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    build(1,1,n);
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>t1>>t2>>t3;
        if(t2>t3) swap(t2,t3);
        if(t1==0)
        {
            modify(1,1,n,t2,t3);
        }
        else
        {
            cout<<query(1,1,n,t2,t3).sum<<endl;
        }
    }
}


上一篇:AGC028F(dp)


下一篇:题解「ZJOI2019 语言」