雪(二分)(树状数组)

Posted fengxunling

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了雪(二分)(树状数组)相关的知识,希望对你有一定的参考价值。

技术分享图片
我们可以先算出来雪堆在哪一天融化完。因为每天都有融化的量,在该天前的雪堆如果没有融化完成的话还会融化,所以记录融化量的前缀和,序列就有了单调性。

有了单调递增的性质后,就可以用二分查找来降低这个复杂度了。(当然懒得打二分可以用lower_bound)

之后算出来在哪一天融化之后,就把该天到那一天的范围内都加上1(可以用树状数组,也可以用线段树)

注意如果不是在那一天刚好融化完要记录余数的。

还有数据范围很大,记得开long long(好吧,我是直接define int long long了)

下面是代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 100010
#define int long long
using namespace std;
int n;
int t[MAXN],sum[MAXN],tag[MAXN],qian[MAXN],v[MAXN],yu[MAXN];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline void push_up(int x){sum[x]=sum[ls(x)]+sum[rs(x)];}
inline void solve(int x,int l,int r,int k)
{
    tag[x]+=k;
    sum[x]+=k*(r-l+1);
}
inline void push_down(int x,int l,int r)
{
    int mid=(l+r)>>1;
    solve(ls(x),l,mid,tag[x]);
    solve(rs(x),mid+1,r,tag[x]);
    tag[x]=0;
}
inline void build(int x,int l,int r)
{
    if(l==r)
    {
        sum[x]=v[l];
        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,int k)
{
    if(ll>rr) return;
    if(ll<=l&&r<=rr)
    {
        sum[x]+=(r-l+1)*k;
        tag[x]+=k;
        return;
    }
    int mid=(l+r)>>1;
    push_down(x,l,r);
    if(ll<=mid) update(ls(x),l,mid,ll,rr,k);
    if(mid<rr) update(rs(x),mid+1,r,ll,rr,k);
    push_up(x);
}
inline int query(int x,int l,int r,int ll,int rr)
{
    if(ll<=l&&r<=rr) return sum[x];
    int mid=(l+r)>>1;
    push_down(x,l,r);
    long long ans=0;
    if(ll<=mid) ans+=query(ls(x),l,mid,ll,rr);
    if(mid<rr) ans+=query(rs(x),mid+1,r,ll,rr);
    return ans;
}
signed main()
{
    freopen("snow.in","r",stdin);
    freopen("snow.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&v[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&t[i]),qian[i]=qian[i-1]+t[i];
    for(int i=1;i<=n;i++)
    {
        v[i]+=qian[i-1];
        int cur=lower_bound(qian+i,qian+1+n,v[i])-qian;
        if(qian[cur]==v[i])
            update(1,1,n,i,cur,1);
        else 
        {
            update(1,1,n,i,cur-1,1);
            yu[cur]+=v[i]-qian[cur-1];
        }
    }
    for(int i=1;i<=n;i++)
    {
        int ans=t[i]*query(1,1,n,i,i);
        ans+=yu[i];
        printf("%lld ",ans);
    }
    return 0;
}

以上是关于雪(二分)(树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

POJ--2182剩余第K大(暴力/树状数组+二分)

POJ--2182剩余第K大(暴力/树状数组+二分)

UVA - 1471 Defense Lines 树状数组/二分

poj 2892Tunnel Warfare 二分+树状数组

51nod 第K大区间2(二分+树状数组)

LIS 树状数组优化