zoukankan      html  css  js  c++  java
  • HDU

    http://acm.hdu.edu.cn/showproblem.php?pid=6315

    题意

    a数组初始全为0,b数组为1-n的一个排列。q次操作,一种操作add给a[l...r]加1,另一种操作query查询Σfloor(ai/bi)(i=l...r)。

    分析

    真的是太naive啦,现场时没做出来。

    看见区间自然想起线段树,那么这里的关键就是整除问题,只有达到一定数量才会对区间和产生影响。

    反过来想,先把a[i]置为b[i],那么每次add时就是-1操作,当a[i]为0时区间和+1,再把a[i]置为b[i]。这要求我们维护区间最小值和区间和。

    若当前区间最小值大于1时,那么此时对这个区间进行add操作没有实质影响,于是用lazy标记先。当区间最小值为1时,向下更新,不断向下找,找到叶结点,区间和+1,a和lazy重新设置。query时就查询区间和即可。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+5;
    
    int a[N<<2],lazy[N<<2],b[N],sum[N<<2];
    int n;
    void PushDown(int rt){
        if(lazy[rt]){
            lazy[rt<<1]+=lazy[rt];
            lazy[rt<<1|1]+=lazy[rt];
            a[rt<<1]-=lazy[rt];
            a[rt<<1|1]-=lazy[rt];
            lazy[rt]=0;
        }
    }
    void PushUp(int rt){
        a[rt]=min(a[rt<<1],a[rt<<1|1]);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void Build(int l,int r,int rt){
        lazy[rt]=sum[rt]=0;
        if(l==r){
            a[rt]=b[l];
            return;
        }
        int mid = (l+r)>>1;
        Build(l,mid,rt<<1);
        Build(mid+1,r,rt<<1|1);
        PushUp(rt);
    }
    void Update(int L,int R,int l,int r,int rt){
        if(a[rt]>1&&L<=l&&r<=R){
            a[rt]--;
            lazy[rt]++;
            return;
        }
        if(a[rt]==1&&l==r){
            sum[rt]++;
            lazy[rt]=0;
            a[rt]=b[l];
            return;
        }
        PushDown(rt);
        int mid = (r+l)>>1;
        if(L<=mid) Update(L,R,l,mid,rt<<1);
        if(mid<R) Update(L,R,mid+1,r,rt<<1|1);
        PushUp(rt);
    }
    int Query(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R){
            return sum[rt];
        }
        PushDown(rt);
        int mid = (r+l)>>1;
        int ans=0;
        if(L<=mid) ans+=Query(L,R,l,mid,rt<<1);
        if(mid<R) ans+=Query(L,R,mid+1,r,rt<<1|1);
        PushUp(rt);
        return ans;
    }
    int main() {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif // LOCAL
        int q,x,y;
        char op[10];
        while(scanf("%d%d",&n,&q)!=EOF) {
            for(int i=1; i<=n; i++)
                scanf("%d",&b[i]);
            Build(1,n,1);
            for(int i=0; i<q; i++) {
                scanf("%s%d%d",op,&x,&y);
                if(op[0]=='a')
                    Update(x,y,1,n,1);
                else
                    printf("%d
    ",Query(x,y,1,n,1));
            }
        }
        return 0;
    }
  • 相关阅读:
    [转]人生哲理小故事
    取PE文件OriginalFilename解析VERSION资源
    [转]COM对象创建外部机制
    读书的几个步骤
    zoj 2412 Farm Irrigation
    HDU 1575 Tr A
    toj 2843 Diamonds
    HDU 1856 More is better
    toj 2841 Bitwise Reverse
    hdu 1213 How Many Tables
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9374788.html
Copyright © 2011-2022 走看看