hdu6315 Naive Operations

题目链接:戳我

给你两个序列a,b,其中a初始是全空的,b是一个排列。
现在有两种操作:
1、给一个区间的a数组加上1
2、求一个区间\(\sum a[i]/b[i]\)
区间操作想到用数据结构维护。
我们可以知道,\(a[i]/b[i]\)只有在a[i]增加够一个b[i]的时候才会多1的贡献,但是我们再增加a[i]的时候和b[i]进行比较比较麻烦(但其实也应该是可以做的),所以我们考虑转化成b[i]-1。
如果b[i]的区间最小值大于1,直接区间减法即可。如果不是,那么寻找那个值为1的,把它改成初始b[i]。
具体见代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define MAXN 100010
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
    return x*f;
}
int n,q;
int a[MAXN],b[MAXN];
struct Node{long long sum,valb,minn,tag;}t[MAXN<<2];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline void push_up(int x)
{
    t[x].minn=min(t[ls(x)].minn,t[rs(x)].minn);
    t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
}
inline void push_down(int x)
{
    if(t[x].tag)
    {
        t[ls(x)].tag+=t[x].tag;
        t[rs(x)].tag+=t[x].tag;
        t[ls(x)].minn-=t[x].tag;
        t[rs(x)].minn-=t[x].tag;
        t[x].tag=0;
    }
}
inline void build(int x,int l,int r)
{
    t[x].tag=t[x].sum=0;
    if(l==r)
    {
        t[x].minn=t[x].valb=b[l];
        t[x].sum=0;
        return;
    }
    int mid=(l+r)>>1;
    build(ls(x),l,mid);
    build(rs(x),mid+1,r);
    push_up(x);
}
inline void update(int x,int l,int r,int ll,int rr)
{
    if(ll<=l&&r<=rr&&t[x].minn>1)
    {
        t[x].tag++;
        t[x].minn--;
        return;
    }
    if(l==r&&t[x].minn==1)
    {
        t[x].sum++;
        t[x].minn=t[x].valb;
        t[x].tag=0;
        return;
    }
    int mid=(l+r)>>1;
    push_down(x);
    if(ll<=mid) update(ls(x),l,mid,ll,rr);
    if(mid<rr) update(rs(x),mid+1,r,ll,rr);
    push_up(x);
}
inline long long query(int x,int l,int r,int ll,int rr)
{
    if(ll<=l&&r<=rr) return t[x].sum;
    int mid=(l+r)>>1;
    push_down(x);
    long long cur_ans=0;
    if(ll<=mid) cur_ans+=query(ls(x),l,mid,ll,rr);
    if(mid<rr) cur_ans+=query(rs(x),mid+1,r,ll,rr);
    return cur_ans;
}
int main()
{
    while(~scanf("%d%d",&n,&q))
    {
        for(int i=1;i<=n;i++) b[i]=read();
        build(1,1,n);
        while(q--)
        {
            string str;
            cin>>str;
            // cout<<str<<endl;
            int l=read(),r=read();
            if(str[0]=='a') update(1,1,n,l,r);
            else printf("%lld\n",query(1,1,n,l,r));
        }
    }
    return 0;
}
posted @ 2019-07-03 22:03  风浔凌  阅读(168)  评论(0编辑  收藏  举报