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

  考虑区间[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<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,a[N],s[][N];
struct data{int l,r,sum,lazy[];
}tree[N<<];
inline void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
inline void up(int k){tree[k].sum=tree[k<<].sum+tree[k<<|].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-]+P)%P);
inc(tree[k].lazy[op],x);
}
inline void down(int k,int i)
{
update(k<<,tree[k].lazy[i],i),
update(k<<|,tree[k].lazy[i],i),
tree[k].lazy[i]=;
}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
if (l==r) return;
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,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[]) down(k,);
if (tree[k].lazy[]) down(k,);
if (tree[k].lazy[]) down(k,);
int mid=tree[k].l+tree[k].r>>;
if (r<=mid) add(k<<,l,r,x,op);
else if (l>mid) add(k<<|,l,r,x,op);
else add(k<<,l,mid,x,op),add(k<<|,mid+,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[]) down(k,);
if (tree[k].lazy[]) down(k,);
if (tree[k].lazy[]) down(k,);
int mid=tree[k].l+tree[k].r>>;
if (r<=mid) return query(k<<,l,r);
else if (l>mid) return query(k<<|,l,r);
else return (query(k<<,l,mid)+query(k<<|,mid+,r))%P;
}
void modify(int l,int r,int x)
{
add(,r,n,1ll*(r-l+)*x%P,),add(,r,n,P-1ll*(s[][r]-s[][l-]+P)*x%P,);
add(,l,r-,1ll*x*inv%P,),add(,l,r-,1ll*x*(P+-l-inv)%P,),add(,l,r-,1ll*l*(l-)%P*inv%P*x%P,);
}
void change(int l,int r,int x)
{
add(,,n,1ll*(r-l+)*x%P,);
modify(l,r,P-x),modify(n-r+,n-l+,P-x);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5291.in","r",stdin);
freopen("bzoj5291.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
build(,,n);
for (int i=;i<=n;i++) s[][i]=s[][i-]+,s[][i]=(s[][i-]+i)%P,s[][i]=(s[][i-]+1ll*i*i)%P;
for (int i=;i<=n;i++) change(i,i,read());
while (m--)
{
int op=read();
if (op==)
{
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\n",query(,l,r));
}
}
return ;
}

BZOJ5291 BJOI2018链上二次求和(线段树)的更多相关文章

  1. [BZOJ5291][BJOI2018]链上二次求和(线段树)

    感觉自己做的麻烦了,但常数似乎不算差.(只是Luogu最慢的点不到2s本地要跑10+s) 感觉我的想法是最自然的,但不明白为什么网上似乎找不到这种做法.(不过当然所有的做法都是分类大讨论,而我的方法手 ...

  2. BZOJ5291/洛谷P4458/LOJ#2512 [Bjoi2018]链上二次求和 线段树

    原文链接http://www.cnblogs.com/zhouzhendong/p/9031130.html 题目传送门 - LOJ#2512 题目传送门 - 洛谷P4458 题目传送门 - BZOJ ...

  3. 2018.01.04 bzoj5291: [Bjoi2018]链上二次求和(线段树)

    传送门 线段树基础题. 题意:给出一个序列,要求支持区间加,查询序列中所有满足区间长度在[L,R][L,R][L,R]之间的区间的权值之和(区间的权值即区间内所有数的和). 想题555分钟,写题202 ...

  4. 【BZOJ5291】[BJOI2018]链上二次求和(线段树)

    [BZOJ5291][BJOI2018]链上二次求和(线段树) 题面 BZOJ 洛谷 题解 考虑一次询问\([l,r]\)的答案.其中\(S\)表示前缀和 \(\displaystyle \sum_{ ...

  5. bzoj 5291: [Bjoi2018]链上二次求和

    Description 有一条长度为n的链(1≤i<n,点i与点i+1之间有一条边的无向图),每个点有一个整数权值,第i个点的权值是 a_i.现在有m个操作,每个操作如下: 操作1(修改):给定 ...

  6. 洛谷P4458 /loj#2512.[BJOI2018]链上二次求和(线段树)

    题面 传送门(loj) 传送门(洛谷) 题解 我果然是人傻常数大的典型啊-- 题解在这儿 //minamoto #include<bits/stdc++.h> #define R regi ...

  7. loj2512 [BJOI2018]链上二次求和

    传送门 分析 咕咕咕 代码 #include<iostream> #include<cstdio> #include<cstring> #include<st ...

  8. 「BJOI2018」链上二次求和

    「BJOI2018」链上二次求和 https://loj.ac/problem/2512 我说今天上午写博客吧.怕自己写一上午,就决定先写道题. 然后我就调了一上午线段树. 花了2h找到lazy标记没 ...

  9. [bzoj5291]链上二次求和

    记$bi=b_{i-1}+ai$,$ci=c_{i-1}+bi$,那么答案就是$\sum_{i=l}^{r}\sum_{j=0}^{n-i}b_{j+i}-bj=(r-l+1)cn-\sum_{i=l ...

随机推荐

  1. 从《乱世王者》看腾讯SLG手游如何搭建完整安全服务

    WeTest 导读 <乱世王者>是由腾讯旗下天美工作室群自主研发的一款战争策略手游,在经历了2015年-2017年的SLG品类手游的爆发之势下,于2017年11月21日正式公测. < ...

  2. MySQL数据库语法(一)

    MySQL数据库语法 数据库管理系统(DBMS)的概述 什么是DBMS:数据的仓库 方便查询 可存储的数据量大 保证数据的完整.一致 安全可靠 DBMS的发展:今天主流数据库为关系型数据库管理系统(R ...

  3. java项目部署之后,Jar包中配置文件修改

    Java项目发布时,配置文件不像.net项目一样与工程路径保持一致,而是直接包含在了jar包中,此时要修改就没那么方便了,我们可以将配置文件从jar包抽离出来,修改完之后再写入Jar包即可, 也没那么 ...

  4. jquery 3.0 新版本

    https://code.jquery.com/

  5. 【坚持】Selenium+Python学习记录 DAY11

    2018/06/1-2018/06/4 参考资料: [菜鸟教程](http://www.runoob.com/python3/python3-examples.html) [Python解惑:True ...

  6. Go的CSP并发模型

    golang的goroutine机制:        一.go 内部有三个对象: P对象(processor) 代表上下文(或者可以认为是cpu),M(work thread)代表工作线程,G对象(g ...

  7. P4562 [JXOI2018]游戏

    题面 题目描述 她长大以后创业了,开了一个公司. 但是管理公司是一个很累人的活,员工们经常背着可怜偷懒,可怜需要时不时对办公室进行检查. 可怜公司有 \(n\) 个办公室,办公室编号是 \(l\) 到 ...

  8. asp.net core如何修改程序监听的端口

    asp.net core 默认监听的5000和5001端口,要修改为其他端口有几种方法. 1.硬编码.优点是直观,缺点是每次修改端口都得重新编译程序. public class Program { p ...

  9. ansible使用1

    常用软件安装及使用目录   ansible软件2 ### ansible软件部署安装需求#### 01. 需要有epel源 系统yum源(base epel--pip gem) sshpass---e ...

  10. Windows搭建python开发环境

    python你不去认识它,可能没什么,一旦你认识了它,你就会爱上它 基本概念Python(英语发音:/ˈpaɪθən/), 是一种面向对象.解释型计算机程序设计语言,由Guido van Rossum ...