zoukankan      html  css  js  c++  java
  • 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;
    
    }
    
  • 相关阅读:
    Redis源代码分析(十三)--- redis-benchmark性能測试
    kvm中运行kvm
    umount.nfs device busy day virsh extend diskSpace, attachDisk
    ultravnc
    openNebula dubug
    maintenance ShellScripts
    virsh VMI deploy data serial xml
    cloud computing platform,virtual authentication encryption
    基于C 的libvirt 接口调用
    storage theory
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754876.html
Copyright © 2011-2022 走看看