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<''||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链上二次求和(线段树)的更多相关文章
- [BZOJ5291][BJOI2018]链上二次求和(线段树)
感觉自己做的麻烦了,但常数似乎不算差.(只是Luogu最慢的点不到2s本地要跑10+s) 感觉我的想法是最自然的,但不明白为什么网上似乎找不到这种做法.(不过当然所有的做法都是分类大讨论,而我的方法手 ...
- BZOJ5291/洛谷P4458/LOJ#2512 [Bjoi2018]链上二次求和 线段树
原文链接http://www.cnblogs.com/zhouzhendong/p/9031130.html 题目传送门 - LOJ#2512 题目传送门 - 洛谷P4458 题目传送门 - BZOJ ...
- 2018.01.04 bzoj5291: [Bjoi2018]链上二次求和(线段树)
传送门 线段树基础题. 题意:给出一个序列,要求支持区间加,查询序列中所有满足区间长度在[L,R][L,R][L,R]之间的区间的权值之和(区间的权值即区间内所有数的和). 想题555分钟,写题202 ...
- 【BZOJ5291】[BJOI2018]链上二次求和(线段树)
[BZOJ5291][BJOI2018]链上二次求和(线段树) 题面 BZOJ 洛谷 题解 考虑一次询问\([l,r]\)的答案.其中\(S\)表示前缀和 \(\displaystyle \sum_{ ...
- bzoj 5291: [Bjoi2018]链上二次求和
Description 有一条长度为n的链(1≤i<n,点i与点i+1之间有一条边的无向图),每个点有一个整数权值,第i个点的权值是 a_i.现在有m个操作,每个操作如下: 操作1(修改):给定 ...
- 洛谷P4458 /loj#2512.[BJOI2018]链上二次求和(线段树)
题面 传送门(loj) 传送门(洛谷) 题解 我果然是人傻常数大的典型啊-- 题解在这儿 //minamoto #include<bits/stdc++.h> #define R regi ...
- loj2512 [BJOI2018]链上二次求和
传送门 分析 咕咕咕 代码 #include<iostream> #include<cstdio> #include<cstring> #include<st ...
- 「BJOI2018」链上二次求和
「BJOI2018」链上二次求和 https://loj.ac/problem/2512 我说今天上午写博客吧.怕自己写一上午,就决定先写道题. 然后我就调了一上午线段树. 花了2h找到lazy标记没 ...
- [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 ...
随机推荐
- Unity扩展编辑器三
Scene视图是编辑游戏模型的地方,其实它还可以进行编辑,如下图所示,我给Scene视图做了简单的编辑 Scene视图的扩展是基于对象的,意思是你必须在Hierarchy视图中选择一个对象才行,Hie ...
- 随机图片api
什么是随机图片api 随机图片api是什么呢?通俗的讲就是当你访问一个api时,浏览器会随机返回给你一张图片. 其实原理很简单,把你要随机的图片放在一起,然后写一个php,当php被访问时,就随机指向 ...
- SICP读书笔记 2.2
SICP CONCLUSION 让我们举起杯,祝福那些将他们的思想镶嵌在重重括号之间的Lisp程序员 ! 祝我能够突破层层代码,找到住在里计算机的神灵! 目录 1. 构造过程抽象 2. 构造数据抽象 ...
- centos7以上安装python3,一条命令搞定。
直接复制下面的命令就搞定 yum install python34 python34-pip python34-setuptools 使用方法: python3 ---.py pip3 install ...
- To Do List | 事实上是咕咕咕计划
1.写一两篇关于数学的博文 类似于这种反演啥的或者说是FFT一些更本质的东西趴...反正是我根本不会的东西 再写一点自己会的东西趴...(好像也只有什么课本上的东西讲讲了,不过应该会写一些自己曾经发现 ...
- tar.gz 文件解压 (安装 netbean 时会用到)
sudo tar xvf jdk-7u45-linux-i586.tar.gz -C /usr/lib 参考文章 http://hi.baidu.com/xiaomeng008/item/5e787b ...
- stat命令详解
基础命令学习目录首页 原文链接:https://blog.csdn.net/yexiangcsdn/article/details/81012732 stat命令用于显示文件的状态信息.stat命令的 ...
- C++ 函数 函数的重载 有默认参数的函数
函数的重载 C++允许用同一函数名定义多个函数,这些函数的参数个数和参数类型不同.这就是函数的重载(function overloading). int max1(int a,int b, int c ...
- final用户体验报告
本次没有新增用户,所联系的用户与beta版本相同 用户序号 用户来源 用户下载软件途径 用户姓名 用户描述(信息) 使用次数 用户评价 1 张恩聚 QQ发送可执行文件 周楠 吉林大学在读研究生 ...
- OO学习总结与体会
前言 经过了对于面向对象程序设计的一个月的学习,我初尝了JAVA以及面向对象程序的魅力.经历了三次难度逐渐加大的课后编程作业,我对于工程化面向对象编程以及调试有了深刻的认识与颇多感想.我写下本篇文章以 ...