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;
    
    }
    
  • 相关阅读:
    监听手机晃动(摇一摇)SensorEventListener
    adb logcat 命令行用法
    设计模式:观察者模式
    设计模式学习笔记-观察者模式
    Android中Parcelable序列化总结
    2048 Puzzle游戏攻略
    projecteuler----&gt;problem=14----Longest Collatz sequence
    桥模式设计模式进入Bridge
    SessionA和pplication网上聊天室的网络范例
    [ACM] hdu 5045 Contest (减少国家Dp)
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754877.html
Copyright © 2011-2022 走看看