zoukankan      html  css  js  c++  java
  • BZOJ5291 BJOI2018链上二次求和(线段树)

      用线段树对每种长度的区间维护权值和。

      考虑区间[l,r]+1对长度为k的区间的贡献,显然其为Σk-max(0,k-i)-max(0,k-(n-i+1)) (i=l~r)。

      大力展开讨论。首先变成Σk-Σmax(0,k-i)-Σmax(0,k-(n-i+1)) (i=l~r)。

      第一部分是一个常数,线段树上是加了一个等差数列。打上标记即可。

      后面两部分本质相同,现考虑Σmax(0,k-i) (i=l~r)。去掉max,即Σk-i (i=l~min(r,k))。根据r和k的大小关系讨论。若r<=k,线段树上加了一个一次函数;若r>k,线段树上加了一个二次函数。三种标记即可。

      常数巨大,下传标记时判一下是否有标记需要传可以快至少一倍。读入序列直接当做修改就能跑过。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    #define P 1000000007
    #define inv 500000004
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,a[N],s[3][N];
    struct data{int l,r,sum,lazy[3];
    }tree[N<<2];
    inline void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
    inline void up(int k){tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;if (tree[k].sum>=P) tree[k].sum-=P;}
    inline void update(int k,int x,int op)
    {
        inc(tree[k].sum,1ll*x*(s[op][tree[k].r]-s[op][tree[k].l-1]+P)%P);
        inc(tree[k].lazy[op],x);
    }
    inline void down(int k,int i)
    {
        update(k<<1,tree[k].lazy[i],i),
        update(k<<1|1,tree[k].lazy[i],i),
        tree[k].lazy[i]=0;
    }
    void build(int k,int l,int r)
    {
        tree[k].l=l,tree[k].r=r;
        if (l==r) return;
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    void add(int k,int l,int r,int x,int op)
    {
        if (l>r) return;
        if (tree[k].l==l&&tree[k].r==r) {update(k,x,op);return;}
        if (tree[k].lazy[0]) down(k,0);
        if (tree[k].lazy[1]) down(k,1);
        if (tree[k].lazy[2]) down(k,2);
        int mid=tree[k].l+tree[k].r>>1;
        if (r<=mid) add(k<<1,l,r,x,op);
        else if (l>mid) add(k<<1|1,l,r,x,op);
        else add(k<<1,l,mid,x,op),add(k<<1|1,mid+1,r,x,op);
        up(k);
    }
    int query(int k,int l,int r)
    {
        if (tree[k].l==l&&tree[k].r==r) return tree[k].sum;
        if (tree[k].lazy[0]) down(k,0);
        if (tree[k].lazy[1]) down(k,1);
        if (tree[k].lazy[2]) down(k,2);
        int mid=tree[k].l+tree[k].r>>1;
        if (r<=mid) return query(k<<1,l,r);
        else if (l>mid) return query(k<<1|1,l,r);
        else return (query(k<<1,l,mid)+query(k<<1|1,mid+1,r))%P;
    }
    void modify(int l,int r,int x)
    {
        add(1,r,n,1ll*(r-l+1)*x%P,1),add(1,r,n,P-1ll*(s[1][r]-s[1][l-1]+P)*x%P,0);
        add(1,l,r-1,1ll*x*inv%P,2),add(1,l,r-1,1ll*x*(P+1-l-inv)%P,1),add(1,l,r-1,1ll*l*(l-1)%P*inv%P*x%P,0);
    }
    void change(int l,int r,int x)
    {
        add(1,1,n,1ll*(r-l+1)*x%P,1);
        modify(l,r,P-x),modify(n-r+1,n-l+1,P-x);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5291.in","r",stdin);
        freopen("bzoj5291.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        build(1,1,n);
        for (int i=1;i<=n;i++) s[0][i]=s[0][i-1]+1,s[1][i]=(s[1][i-1]+i)%P,s[2][i]=(s[2][i-1]+1ll*i*i)%P;
        for (int i=1;i<=n;i++) change(i,i,read());
        while (m--)
        {
            int op=read();
            if (op==1)
            {
                int l=read(),r=read(),x=read();
                if (l>r) swap(l,r);
                change(l,r,x);
            }
            else
            {
                int l=read(),r=read();
                printf("%d
    ",query(1,l,r));
            }
        }
        return 0;
    }
  • 相关阅读:
    ffmpeg rtmp推流 视频转码
    java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
    nginx stream 流转发,可以转发rtmp、mysql访问流,转发rtmp、jdbc请求
    java web http 转https 通过nginx代理访问
    linux 服务器磁盘挂载
    novnc 通过websockify代理 配置多点访问
    linux 文件服务 minio 安装部署配置
    AOP实现原理,手写aop
    java 泛型
    JAVA反射getGenericSuperclass()用法
  • 原文地址:https://www.cnblogs.com/Gloid/p/10111186.html
Copyright © 2011-2022 走看看