Description

有一条长度为n的链(1≤i<n,点i与点i+1之间有一条边的无向图),每个点有一个整数权值,第i个点的权值是

a_i。现在有m个操作,每个操作如下:

操作1(修改):给定链上两个节点u、v和一个整数d,表示将链上u到v唯一的简单路径上每个点权值都加上d。

操作2(询问):给定两个正整数L、r,表示求链上所有节点个数大于等于L且小于等于r的简单路径节点权值和之和。

由于答案很大,只用输出对质数1000000007取模的结果即可。

一条节点个数为k的简单路径节点权值和为这条上所有k个节点(包括端点)的权值之和,

而本题中要求是对所有满足要求的简单路径,求这一权值和的和。

由于是无向图,路径也是无向的,即点1到点2的路径与点2到点1的路径是同一条,不要重复计算。

Solution

开始想考虑每个点的贡献,然后发现要分三段讨论,并且维护的东西有点多,写不下去了

最后直接模拟题意:

设 \(s_i\) 为 \(a_i\) 的前缀和, \(ss_i\) 为 \(s_i\) 的前缀和

求 \(\sum_{k=l}^r\sum_{i=k}^n (s_i-s_{i-k})\)

\(\sum_{k=l}^r (\sum_{i=k}^{n}s_i-\sum_{i=0}^{n-k}s_i)\)

\(\sum_{k=l}^r (ss_n-ss_{k-1}-ss_{n-k})\)

\((r-l+1)*ss_n-\sum_{k=l-1}^{r-1}ss_k-\sum_{k=n-r}^{n-l}ss_k\)

线段树维护 \(ss\) 就好了

关于修改:

分两段考虑:

\(l<=i<=r\),\(ss_i\) 加上 \(d*\frac{(i-l+1)*(i-l+2)}{2}\)

\(r<i<=n\), \(ss_i\) 加上 \(d*(\frac{(r-l+1)*(r-l+2)}{2}+(r-l+1)*(i-r)*d)\)

分别是关于 \(i\) 的二次函数和一次函数

维护系数 \(a,b,c\) 就好了

#include<bits/stdc++.h>
#define ls (o<<1)
#define rs (o<<1|1)
using namespace std;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=2e5+10,mod=1e9+7,inv=166666668,inv2=500000004;
int n,Q,a[N],s[N],ss[N],tr[N*4],A[N*4],B[N*4],C[N*4];
int la,lb,lc;
inline int S1(int l,int r){return (1ll*(l+r)*(r-l+1)>>1)%mod;}
inline int S2(int l,int r){
int rr=1ll*r*(r+1)%mod*((r<<1)+1)%mod;l--;
int ll=1ll*l*(l+1)%mod*((l<<1)+1)%mod;
return 1ll*(rr-ll+mod)*inv%mod;
}
inline void upd(int o){tr[o]=(tr[ls]+tr[rs])%mod;}
inline void build(int l,int r,int o){
if(l==r){tr[o]=ss[l];return ;}
int mid=(l+r)>>1;
build(l,mid,ls);build(mid+1,r,rs);
upd(o);
}
inline void pushdown(int o,int l,int r){
if(!A[o]&&!B[o]&&!C[o])return ;
int mid=(l+r)>>1;
A[ls]=(A[ls]+A[o])%mod;B[ls]=(B[ls]+B[o])%mod;C[ls]=(C[ls]+C[o])%mod;
A[rs]=(A[rs]+A[o])%mod;B[rs]=(B[rs]+B[o])%mod;C[rs]=(C[rs]+C[o])%mod; tr[ls]=(tr[ls]+1ll*S2(l,mid)*A[o])%mod;
tr[ls]=(tr[ls]+1ll*S1(l,mid)*B[o])%mod;
tr[ls]=(tr[ls]+1ll*(mid-l+1)*C[o])%mod;
tr[rs]=(tr[rs]+1ll*S2(mid+1,r)*A[o])%mod;
tr[rs]=(tr[rs]+1ll*S1(mid+1,r)*B[o])%mod;
tr[rs]=(tr[rs]+1ll*(r-mid)*C[o])%mod; A[o]=B[o]=C[o]=0;
}
inline void mdf(int l,int r,int o,int sa,int se){
if(sa<=l && r<=se){
A[o]=(A[o]+la)%mod;B[o]=(B[o]+lb)%mod;C[o]=(C[o]+lc)%mod;
tr[o]=(tr[o]+1ll*S2(l,r)*la)%mod;
tr[o]=(tr[o]+1ll*S1(l,r)*lb)%mod;
tr[o]=(tr[o]+1ll*(r-l+1)*lc)%mod;
return ;
}
pushdown(o,l,r);
int mid=(l+r)>>1;
if(se<=mid)mdf(l,mid,ls,sa,se);
else if(sa>mid)mdf(mid+1,r,rs,sa,se);
else mdf(l,mid,ls,sa,mid),mdf(mid+1,r,rs,mid+1,se);
upd(o);
}
inline int qry(int l,int r,int o,int sa,int se){
if(sa<=l && r<=se)return tr[o];
pushdown(o,l,r);
int mid=(l+r)>>1;
if(se<=mid)return qry(l,mid,ls,sa,se);
if(sa>mid)return qry(mid+1,r,rs,sa,se);
return (qry(l,mid,ls,sa,mid)+qry(mid+1,r,rs,mid+1,se))%mod;
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>Q;
for(int i=1;i<=n;i++)
gi(a[i]),s[i]=(s[i-1]+a[i])%mod,ss[i]=(ss[i-1]+s[i])%mod;
build(1,n,1);
int op,x,y,z;
while(Q--){
gi(op);gi(x);gi(y);
if(x>y)swap(x,y);
if(op==1){
gi(z);
z=1ll*z*inv2%mod;
la=z;lb=1ll*(3-2*x)*z%mod;lc=1ll*z*((1ll*x*x-3*x+2)%mod)%mod;
if(lb<0)lb+=mod;if(lc<0)lc+=mod;
mdf(1,n,1,x,y);
if(y<n){
z=1ll*z*2%mod;
la=0;lb=1ll*(y-x+1)*z%mod;
lc=(1ll*z*((1ll*(y-x+1)*(y-x+2)/2-1ll*(y-x+1)*y)%mod))%mod;
if(lc<0)lc+=mod;
mdf(1,n,1,y+1,n);
}
}
else{
int ans=1ll*(y-x+1)*qry(1,n,1,n,n)%mod;
if(y-1>0)ans=(1ll*ans-qry(1,n,1,max(x-1,1),y-1)+mod)%mod;
if(n-x>0)ans=(1ll*ans-qry(1,n,1,max(n-y,1),n-x)+mod)%mod;
printf("%d\n",ans);
}
}
return 0;
}

bzoj 5291: [Bjoi2018]链上二次求和的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. 「BJOI2018」链上二次求和

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

  9. 【LOJ】#2512. 「BJOI2018」链上二次求和

    题面 题解 转化一下可以变成所有小于等于r的减去小于等于l - 1的 然后我们求小于等于x的 显然是 \(\sum_{i = 1}^{n} \sum_{j = 1}^{min(i,x)} sum[i] ...

随机推荐

  1. JavaScript 如何工作:渲染引擎和性能优化技巧

    翻译自:How JavaScript works: the rendering engine and tips to optimize its performance 这是探索 JavaScript ...

  2. python-判断语句介绍

    1.生活中的判断场景 1.1 火车站安检 1.2 上网吧 2.开发中的判断场景 2.1 密码判断 2.2 重要日期判断 if 今天是周六或者周日: 约妹子 if 今天是情人节: 买玫瑰 if 今天发工 ...

  3. Udp 网络字节序

    1.网络上的数据是一个字节一个字节的串行传递的. 2.字节序,规定,在内存里存储时,低字节在前称为小端,高字节在前称为大端,(现在主流系统都是小端的) 3.网络字节序,如果先传高字节,则是大端传输:如 ...

  4. 数学【洛谷P4071】 [SDOI2016]排列计数

    P4071 [SDOI2016]排列计数 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列 ...

  5. MYSQL 面试常见问题汇总

    转自: https://blog.csdn.net/u011010851/article/details/80074550 Q1:主键,外键,超键,候选键:主键    对表中数据进行唯一标识的数据列的 ...

  6. Qt 学习之路 2(28):坐标系统

    Qt 学习之路 2(28):坐标系统 豆子 2012年11月25日 Qt 学习之路 2 59条评论 在经历过实际操作,以及前面一节中我们见到的那个translate()函数之后,我们可以详细了解下 Q ...

  7. 16. js 判断变量类型,包括ES6 新类型Symbol

    相信大家在开发中遇到需要判断变量类型的问题,js变量按存储类型可分为值类型和引用类型,值类型包括Undefined.String.Number.Boolean,引用类型包括object.Array.F ...

  8. Android 通知(Notification)

    1.介绍 2.常用属性 3.java后台代码 package com.lucky.test30notification; import android.app.Notification; import ...

  9. 未在本地计算机上注册microsoft.jet

      未在本地计算机上注册microsoft.jet http://www.microsoft.com/zh-cn/download/confirmation.aspx?id=13255

  10. Sasha and a Bit of Relax(前缀异或和+二维数组+思维)

    Sasha likes programming. Once, during a very long contest, Sasha decided that he was a bit tired and ...