题面

传送门(loj)

传送门(洛谷)

题解

我果然是人傻常数大的典型啊……

题解在这儿

//minamoto
#include<bits/stdc++.h>
#define R register
#define ls (p<<1)
#define rs (p<<1|1)
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int K=-1,Z=0;
inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
void print(R int x){
if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++K]=z[Z],--Z);sr[++K]='\n';
}
const int N=2e5+5,P=1e9+7,inv2=500000004,inv6=166666668;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
return res;
}
struct node{int l,r,a,b,sum[2];}tr[N<<2];
int a[N],n,m;
inline int f(R int x){return 1ll*x*(x+1)%P*((x<<1ll)+1)%P*inv6%P;}
void ppd(int p,int a,int b){
int sz=tr[p].r-tr[p].l;
tr[p].sum[0]=add(tr[p].sum[0],1ll*add(mul(2,a),mul(b,sz))*(sz+1)%P*inv2%P);
tr[p].sum[1]=add(tr[p].sum[1],1ll*a*(tr[p].l+tr[p].r)%P*(sz+1)%P*inv2%P);
tr[p].sum[1]=add(tr[p].sum[1],1ll*tr[p].l*b%P*sz%P*(sz+1)%P*inv2%P);
tr[p].sum[1]=add(tr[p].sum[1],mul(b,f(sz)));
tr[p].a=add(tr[p].a,a),tr[p].b=add(tr[p].b,b);
}
void upd(int p){
tr[p].sum[0]=add(tr[ls].sum[0],tr[rs].sum[0]);
tr[p].sum[1]=add(tr[ls].sum[1],tr[rs].sum[1]);
}
void pd(int p){
int mid=(tr[p].l+tr[p].r)>>1;
ppd(ls,tr[p].a,tr[p].b);
ppd(rs,add(tr[p].a,mul(mid-tr[p].l+1,tr[p].b)),tr[p].b);
tr[p].a=tr[p].b=0;
}
void build(int p,int l,int r){
tr[p].l=l,tr[p].r=r;
if(l==r)return tr[p].sum[0]=a[l],tr[p].sum[1]=mul(l,a[l]),void();
int mid=(l+r)>>1;
build(ls,l,mid),build(rs,mid+1,r);
upd(p);
}
int query(int p,int ql,int qr,int id){
if(ql<=tr[p].l&&qr>=tr[p].r)return tr[p].sum[id];
int mid=(tr[p].l+tr[p].r)>>1;
if(tr[p].a||tr[p].b)pd(p);
int res=0;
if(ql<=mid)res=add(res,query(ls,ql,qr,id));
if(qr>mid)res=add(res,query(rs,ql,qr,id));
return res;
}
void update(int p,int l,int r,int a,int b){
if(l==tr[p].l&&r==tr[p].r)return ppd(p,a,b);
if(tr[p].a||tr[p].b)pd(p);
int mid=(tr[p].l+tr[p].r)>>1;
if(r<=mid)update(ls,l,r,a,b);
else if(l>mid)update(rs,l,r,a,b);
else update(ls,l,mid,a,b),update(rs,mid+1,r,add(a,mul(b,mid+1-l)),b);
upd(p);
}
int calc(int x){
if(!x)return 0;
int res=0;
res=add(res,mul(query(1,x,n,0),x));
if(x!=n)res=add(res,P-mul(query(1,1,n-x,0),x));
if(x!=1)res=add(res,query(1,1,x-1,1));
res=add(res,P-add(mul(n,query(1,n-x+1,n,0)),P-query(1,n-x+1,n,1)));
return res;
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
fp(i,1,n)a[i]=read(),a[i]=add(a[i],a[i-1]);
build(1,1,n);
int op,l,r,d;
while(m--){
op=read(),l=read(),r=read();
if(op==1){
d=read();if(l>r)swap(l,r);
update(1,l,r,d,d);
if(r<n)update(1,r+1,n,mul(d,r-l+1),0);
}else print(dec(calc(r),calc(l-1)));
}
return Ot(),0;
}

洛谷P4458 /loj#2512.[BJOI2018]链上二次求和(线段树)的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ5291 BJOI2018链上二次求和(线段树)

    用线段树对每种长度的区间维护权值和. 考虑区间[l,r]+1对长度为k的区间的贡献,显然其为Σk-max(0,k-i)-max(0,k-(n-i+1)) (i=l~r). 大力展开讨论.首先变成Σk- ...

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

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

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

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

  8. 「BJOI2018」链上二次求和

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

  9. 洛谷P4459/loj#2511 [BJOI2018]双人猜数游戏(博弈论)

    题面 传送门(loj) 传送门(洛谷) 题解 所以博弈论的本质就是爆搜么-- 题解 //minamoto #include<bits/stdc++.h> #define R registe ...

随机推荐

  1. leetcode524

    public class Solution { public string FindLongestWord(string s, IList<string> d) { string long ...

  2. Iterator(迭代器)的一般用法 (转)

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...

  3. java5 CyclicBarrier同步工具

    CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点(common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此 ...

  4. windows上输入其他国家语言

    1.安装语言环境 2.先有语言环境再有该语言下的输入法toolkit工具集. 3.通过特定语言的属性可以查看键盘布局.

  5. linux加入windows域之完美方案

    运行setup工具 认证配置 选择: “use winbind” “use kerberos” “use winbind authertication” 改为: 删除admin server 其余的改 ...

  6. 由于挂载的nfs存储目录掉下线,导致创建VM时,无法创建

    具体错误,如下截图 重新挂载存储后,在创建VM,将成功

  7. 重置CentOS6.5的登录口令

    早先在虚拟机Vmware里安装了一台CentOS6.5,现在想登录,发现无论怎么输入登录口令都不正确,以至于无法登录. 查阅网上资料,可用下面步骤里的方法重置登录口令,在此记录. 1.启动机器,出现下 ...

  8. c语言实践 数字特征值

    这题的要求是这样的: 这题我没做出来,我大概思路是这样的,根据输入的数字,把这个数字的每一位都分离出来,然后判断奇数还是偶数,再判断序是奇数还是偶数,最后两个奇偶性比较,输出1还是0,这个输出的1和0 ...

  9. 显著水平alpha

    http://blog.minitab.com/blog/adventures-in-statistics-2/understanding-hypothesis-tests:-significance ...

  10. javascript总结9:JavaScript三目运算符

    1 三元表达式: 表达式?结果1:结果2: 如果表达式结果为true,执行结果1,如果表达式结果为false,执行结果2. 可以理解为if else  的另外一种写法. 例: var m = 10; ...