题面

传送门(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. spring-cloud配置高可用eureka服务端

    spring-cloud配置eureka服务端 eureka用来发现其他程序 依赖 <?xml version="1.0" encoding="UTF-8" ...

  2. selenium - 驱动 chromedriver 初始化问题总结

    ChromeDriver切换浏览器语言 ChromeOptions options = new ChromeOptions(); options.addArguments("--lang=& ...

  3. 不需要SDK调用图灵机器人的方法

    图灵机器人的调用其实就是你给服务器发一个文字消息过去,他回你一个,看起来模仿人类对话一样. 不知道为什么要弄个SDK这么麻烦的方法,以前的接口官网上已经没有了,但是还是可以用的.返回的是JSON但也懒 ...

  4. POJ1161(并查集)

    1.题目链接地址 http://poj.org/problem?id=1161 2.源代码 #include <iostream> using namespace std; ]; ]; i ...

  5. JAVA基础知识总结18(反射)

    反射技术: 其实就是动态加载一个指定的类,并获取该类中的所有的内容.而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员.简单说:反射技术可以对一个类进行解剖. 反射的 ...

  6. Android4.0+锁屏程序开发——按键屏蔽篇

    开发锁屏程序的时候我们要面临的重要问题无疑是如何屏蔽三个按键,Back,Home,Menu  看似简单的功能,实现起来却并不是那么容易. [屏蔽Back按键] 相对来说,屏蔽Back键是比较简单的,只 ...

  7. docker问题:docker端口映射错误

    1 docker端口映射错误 1.1 问题描述 利用docker启动nginx容器的时候报错: 1.2 解决办法 一次执行下面的命令就可以解决 pkill docker iptables -t nat ...

  8. js数值和字符串比较的规则

    1.数值和字符串比较时 a.若字符串为数字字符串,则将字符串转为数字,再比较 b.若字符串不为数字字符串,则直接返回false,因为这里把字符串转为了NaN, 数字与NaN比较,都返回false

  9. 360 安全卫士 for Linux 使用结果

    测试了一把,结果显示360基本对Linux社区规范和安全常识不give a fuck. 胡乱打包 首先,这个deb包就是胡乱打包,依赖关系就没弄好: $ dpkg-deb -I 360safeforl ...

  10. PCL 常用小知识

    时间计算 pcl中计算程序运行时间有很多函数,其中利用控制台的时间计算 首先必须包含头文件 #include <pcl/console/time.h> #include <pcl/c ...