Naive Operations HDU

传送门

  题意是给一个长度为n的a,b数组,然后有2种操作,一种是a数组l~r区间+1,第二种是查询l~r区间ai/bi之和。维护区间内最大的a值和最小的b值,对一段区间进行成段更新后,如果maxa==minb说明往该节点的儿子节点更新可能会对该区间之和产生贡献,那就更新下去,往下面更新时若找到了maxa==minb的叶子节点,则该叶子节点的minb加上其初始的值(b[l]),且区间和++,比如说2/2,将分母即该节点的minb+b[l],区间之和加1.若maxa<minb的话说明往该节点的儿子节点更新不可能会对该区间之和产生贡献,因此不必更新下去了,在当前节点打个标记即可,查询的话就和普通线段树查询一样。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
#define ll long long
#define ls 2*rt
#define rs 2*rt+1
struct node
{
    ll sum;
    int l,r,lazy,maxa,minb;
    bool tag;
}tree[4*maxn];
int b[maxn+10];
inline void pushup(int rt)
{
    tree[rt].sum=tree[ls].sum+tree[rs].sum;
    tree[rt].maxa=max(tree[ls].maxa,tree[rs].maxa);
    tree[rt].minb=min(tree[ls].minb,tree[rs].minb);
}
inline void pushdown(int rt)
{
    if(tree[rt].tag)
    {
        tree[ls].maxa+=tree[rt].lazy;
        tree[rs].maxa+=tree[rt].lazy;
        tree[ls].tag=true;
        tree[ls].lazy+=tree[rt].lazy;
        tree[rs].tag=true;
        tree[rs].lazy+=tree[rt].lazy;
        tree[rt].tag=false;
        tree[rt].lazy=0;
    }
}
void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].tag=false;
    tree[rt].lazy=0;
    if(l==r)
    {
        tree[rt].maxa=0;
        tree[rt].minb=b[l];
        tree[rt].sum=0;
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,ls);
    build(mid+1,r,rs);
    pushup(rt);
}
void update(int l,int r,int rt)
{
    if(tree[rt].l>=l&&tree[rt].r<=r)
    {
        tree[rt].maxa++;
        if(tree[rt].maxa<tree[rt].minb)///满足该条件则对rt节点对应区间更新不可能对区间和有贡献,当然ls,rs也是一样不会有贡献的,因此不必更新到rt对应区间的每个叶子节点
        {
            tree[rt].tag=true;
            tree[rt].lazy++;
            return ;
        }
        else
            if(tree[rt].l==tree[rt].r)///满足该条件说明这个rt节点对应区间的maxa==minb,说明更新该节点是对区间和有贡献的,且rt节点是叶子节点
            {
                tree[rt].sum++;
                tree[rt].minb+=b[tree[rt].l];
                return ;
            }
    }
    ///执行下面的语句的话,说明rt节点不能成段更新或rt节点能成段更新,更新该节点对应的区间可能对区间和有贡献。这2种情况都需要更新到rt的儿子
    pushdown(rt);
    int mid=(tree[rt].l+tree[rt].r)/2;
    if(mid>=r)
        update(l,r,ls);
    else
        if(mid+1<=l)
            update(l,r,rs);
        else
        {
            update(l,r,ls);
            update(l,r,rs);
        }
    pushup(rt);
}
ll query(int l,int r,int rt)
{
    if(tree[rt].l>=l&&tree[rt].r<=r)
    {
        return tree[rt].sum;
    }
    ll ans=0;
    int mid=(tree[rt].l+tree[rt].r)>>1;
    if(mid>=r)
        ans=query(l,r,ls);
    else
        if(mid+1<=l)
            ans=query(l,r,rs);
        else
        {
            ans=query(l,r,ls); 
            ans+=query(l,r,rs);

        }
    return ans;
}
int main()
{
    int n,q;
    while(scanf("%d %d",&n,&q)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&(b[i]));
        build(1,n,1);
        char op[10];
        int l,r;
        while(q--)
        {
            scanf("%s %d %d",op,&l,&r);
            if(op[0]=='a')
                update(l,r,1);
            else
                printf("%lld
",query(l,r,1));
        }
    }
    return 0;

}
原文地址:https://www.cnblogs.com/eason9906/p/11754877.html