2018多校赛第二场 Naive Operations (线段树+思维)

题意

初始化a数组都为0,b数组的值为一个固定的排列数。
然后有两个操作:
add l r:将a数组[l,r]的值都加1.
query l r:查询区间[l,r]累加和下取整(ai/bi)。

解题

题目出得这么像线段树,那么不妨往线段树方面想。
用线段树维护区间信息sum和c,sum表示下取整之和,c表示这个区间最少需要经过多少次add操作才会导致sum的值加1.
并用一个lazy标记,当sum的值不会因为add操作而改变时只修改当前区间的信息,对其子区间进行lazy标记。
当sum的值会改变时,暴力更新到叶子结点。
这样,每次查询的时间复杂度是O(logn)的,而修改区间的信息的时间复杂度也是O(logn)的,只有暴力更新叶子结点的时间复杂度稍大点。但因为这样的次数并不会太多,所以还是可以接受的。

AC代码

#include <bits/stdc++.h>
#define lson p<<1
#define rson p<<1|1
typedef long long ll;
using namespace std;

const int maxn=1e5+7;
struct node
{
    int l,r;
    ll sum;
    ll c;//a[i]每加c次a[i]/b[i]加1
    int lazy;//当前区间应该累加多少次
}T[maxn<<2];
int b[maxn];

void up(int p)
{
    T[p].sum=T[lson].sum+T[rson].sum;
    T[p].c=min(T[lson].c,T[rson].c);
}
void down(int p)
{
    T[lson].c-=T[p].lazy;
    T[rson].c-=T[p].lazy;
    T[lson].lazy+=T[p].lazy;
    T[rson].lazy+=T[p].lazy;
    T[p].lazy=0;
}
void build(int p,int l,int r)
{
    T[p].l=l,T[p].r=r;T[p].lazy=0;
    T[p].sum=0;
    if(l==r)
    {
        T[p].sum=0;
        T[p].c=b[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    up(p);
}
void update(int p,int x,int y)
{
    if(T[p].l==T[p].r)
    {
        if(T[p].c==1)
        {
            T[p].c=b[T[p].l];
            T[p].lazy=0;
            T[p].sum++;
            return ;
        }
        else
        {
            T[p].c--;
            T[p].lazy++;
            return ;
        }
    }
    if(T[p].l==x && y==T[p].r && T[p].c!=1)
    {
        T[p].c--;
        T[p].lazy++;
        return ;
    }
    down(p);
    int mid=(T[p].l+T[p].r)>>1;
    if(y<=mid) update(lson,x,y);
    else if(x>mid) update(rson,x,y);
    else
    {
        update(lson,x,mid);
        update(rson,mid+1,y);
    }
    up(p);
}
ll query(int p,int x,int y)
{
    ll ans;
    if(T[p].l==x && T[p].r==y)
    {
        return T[p].sum;
    }
    down(p);
    int mid=(T[p].l+T[p].r)>>1;
    if(y<=mid) ans= query(lson,x,y);
    else if(x>mid) ans= query(rson,x,y);
    else
    {
        ll s1=query(lson,x,mid);
        ll s2=query(rson,mid+1,y);
        ans=s1+s2;
    }
    up(p);
    return ans;
}
int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        build(1,1,n);
        while(q--)
        {
            char str[20];
            int x,y;
            scanf("%s%d%d",str,&x,&y);
            if(str[0]=='a') update(1,x,y);
            else printf("%lld\n",query(1,x,y));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37685156/article/details/81254405
今日推荐