HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)

Posted fht-litost

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)相关的知识,希望对你有一定的参考价值。

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;
}

 

以上是关于HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 6315 Naive Operations (线段树+思维) 2018 Multi-University Training Contest 2

HDU 6315: Naive Operations

HDU-DuoXiao第二场hdu 6315 Naive Operations 线段树

hdu 6315(线段树)

[Hdu6315]Naive Operations

HDU6315 Naive Operations(多校第二场1007)(线段树)