Naive Operations HDU - 6315 -思维+线段树

  • G - Naive Operations

  •  HDU - 6315 
  • 题意:给定长度n的数列b[i],m次操作,1:给a[i]一个区间内都加上1;2:求和一个区间a[i]/b[i]向下取整。
  • 思路:区间更新和区间查询。现在就是怎么处理a[i]/b[i]。让线段树维护一个b[i]的最大值,一个a[i]的最小值。
  • sum=a[i]/b[i]。当最大值max小于min是就没有个sum要加一。lazy标记终止往下就行,否则就一直往下直到叶子节点
  • 给叶子节点的b,再加一下b,然后结果sum++,因为这是a已经大于等于b所以结果++。
  • #include
    #include
    #include
    using namespace std;
    #define maxn 105050
    int b[maxn],n,q,l,r;
    struct node
    {
        int l,r,lazy,maxa,minb,sum;
    } tree[maxn*4];
    char str[10];
    void pushup(int root)
    {
        tree[root].minb=min(tree[root<<1].minb,tree[root<<1|1].minb);
        tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
        tree[root].maxa=max(tree[root<<1].maxa,tree[root<<1|1].maxa);
    }
    void pushdown(int root)
    {
        if(tree[root].lazy)
        {
            tree[root<<1].lazy+=tree[root].lazy;
            tree[root<<1|1].lazy+=tree[root].lazy;
            tree[root<<1].maxa+=tree[root].lazy;
            tree[root<<1|1].maxa+=tree[root].lazy;
            tree[root].lazy=0;
        }
    }
    void build(int root,int l,int r)
    {
        tree[root].l=l;
        tree[root].r=r;
        tree[root].lazy=0;
        if(l==r)
        {
            tree[root].maxa=tree[root].sum=0;
            tree[root].minb=b[l];
            return ;
        }
        int mid=(l+r)/2;
        build(root<<1,l,mid);
        build(root<<1|1,mid+1,r);
        pushup(root);
    }
    void updata(int root,int l,int r)
    {
        if(tree[root].l>=l&&tree[root].r<=r)
        {
            tree[root].maxa++;
            if(tree[root].maxa=tree[root].minb)
            {
                tree[root].sum++;
                tree[root].minb+=b[tree[root].l];
                return ;
            }
        }
        pushdown(root);
        int mid=(tree[root].l+tree[root].r)/2;
        if(l<=mid)
            updata(root*2,l,r);
        if(r>mid)
            updata(root*2+1,l,r);
        pushup(root);
    }
    int query(int root,int l,int r)
    {
        if(tree[root].l>=l&&tree[root].r<=r)
            return tree[root].sum;
        pushdown(root);
        int mid=(tree[root].l+tree[root].r)/2,ans=0;
        if(l<=mid)ans+=query(root*2,l,r);
        if(r>mid)ans+=query(root*2+1,l,r);
        return ans;
    }
    int main()
    {
        while(scanf("%d%d",&n,&q)==2)
        {
            for(int i=1; i<=n; i++)
                scanf("%d",&b[i]);
            build(1,1,n);
            while(q--)
            {
                scanf("%s%d%d",str,&l,&r);
                if(strcmp(str,"add")==0)
                    updata(1,l,r);
                else
                    printf("%d\n",query(1,l,r));
            }
        }
        return 0;
    }
  •  

你可能感兴趣的:(线段树)