链接:https://ac.nowcoder.com/acm/contest/917/J
来源:牛客网
外挂
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld题目描述
我的就是我的,你也是我的,记住了,狐狸!
——韩信-白龙吟
对于打赌输了的小T会遭受到制裁,小s修改了数据库使他可以派出许多军队来围攻小T.
很不幸,小T与小s打赌打输了,现在小T遭受着枪林弹雨与十面埋伏,因为小T是神所以他决定要扭转局势。
他要修改数据库!
数据总库的信号墙有n个电极插头,每个插头有一个信号aia_iai,
小T可以使在区间[ l,r ][\ l,r\ ][ l,r ]内的所有信号加上一个值k。
对于区间[ l,r ][\ l,r\ ][ l,r ]的信号强度有一个计算公式:
我们定义
f(k)=ak×∑j=k+1rajf(k)=a_k \times \sum_{j=k+1}^r a_jf(k)=ak×∑j=k+1raj
则信号强度就为:
∑i=lrf(i)\sum_{i=l}^r f(i)∑i=lrf(i)
你可以认为f(i)就是第i个插头的信号强度。
现在小T一会儿修改信号值,一会儿询问信号强度,你是数据库的管理员,为了不被小TD,所以你要告诉他信号强度是多少。
注:本系列题不按难度排序哦
输入描述:
第一行两个整数n,Q 第二行n个整数代表a 后Q行代表操作: 一操作:1 l r x1\ l\ r\ x1 l r x代表区间[ l,r ][\ l,r\ ][ l,r ]加x。 二操作:2 l r2\ l\ r2 l r代表区间询问。
输出描述:
每一行一个数字,表示对于一个二操作的答案。
示例1
输入
复制
5 2 1 2 3 4 5 1 1 2 1 2 1 2
输出
复制
6
说明
样例解释:1 1 2 1使a[1]~a[2]的值每个都加了1, 即a[1]=2, a[2]=3,所以2 1 2=a[1]*a[2]=2*3=6
保证所有二操作的答案都是在long longlong\ longlong long范围内(如果你不相信,可以写高精)。
时空限制为标程的5倍,放心卡常。备注:
100% 1≤n,Q≤105100 \% \ \ 1 \le n,Q \le 10^5100% 1≤n,Q≤105
对于所有ai≤100a_i \le 100ai≤100
【此图转自https://blog.csdn.net/qq_41997978/article/details/92384967】
#include<bits/stdc++.h> #define ll long long #define ls o*2 #define rs o*2+1 #define mid (l+r)/2 using namespace std; ll tree[4*100005],tag[4*100005],qtree[4*100005]; //tree[]区间和 qtree[]区间平方和 ll a[100005]; int n,Q; void pushdown(int o,int l,int r) { if(!tag[o]||l==r) return ;//下传 对子节点修改 而不是对当前节点!!! qtree[ls]+= 2*tag[o]*tree[ls] + tag[o]*tag[o]*(mid-l+1); qtree[rs]+= 2*tag[o]*tree[rs] + tag[o]*tag[o]*(r-mid); //先修改区间平方和 利用之前区间和 tree[ls]+=tag[o]*(mid-l+1); tree[rs]+=tag[o]*(r-mid); tag[ls]+=tag[o]; tag[rs]+=tag[o]; tag[o]=0; } void up(int o,int l,int r,int ql,int qr,ll v) { if(ql<=l&&r<=qr) { qtree[o]+= 2*tree[o]*v + v*v*(r-l+1);//每个数都加 v*v+2*v*a[i] tree[o]+= v*(r-l+1); tag[o]+=v; return ; } pushdown(o,l,r);//下传 if(ql<=mid) up(ls,l,mid,ql,qr,v); if(mid<qr) up(rs,mid+1,r,ql,qr,v); tree[o]=tree[ls]+tree[rs];//pushup 维护区间和 区间平方和 qtree[o]=qtree[ls]+qtree[rs]; return ; } ll qu_sum(int o,int l,int r,int ql,int qr)//获取区间和 { if(ql<=l&&r<=qr) { return tree[o]; } pushdown(o,l,r); ll ans=0; if(ql<=mid) ans+=qu_sum(ls,l,mid,ql,qr); if(mid<qr) ans+=qu_sum(rs,mid+1,r,ql,qr); return ans; } ll qu_qtree(int o,int l,int r,int ql,int qr)//获取区间平方和 { if(ql<=l&&r<=qr) { return qtree[o]; } pushdown(o,l,r); ll ans=0; if(ql<=mid) ans+=qu_qtree(ls,l,mid,ql,qr); if(mid<qr) ans+=qu_qtree(rs,mid+1,r,ql,qr); return ans; } int main() { scanf("%d%d",&n,&Q); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); up(1,1,n,i,i,a[i]); } while(Q--) { int t; scanf("%d",&t); if(t==1) { int l,r; ll x; scanf("%d%d%lld",&l,&r,&x); up(1,1,n,l,r,x); } else { int l,r; scanf("%d%d",&l,&r); ll qtreenum=qu_qtree(1,1,n,l,r); ll sum=qu_sum(1,1,n,l,r); printf("%lld\n",(sum*sum-qtreenum)/2); } } } //6 6 //1 1 1 1 1 1 // //1 1 1 1 1 1 //1 2 4 6
线段树 (维护 区间平方和 Lazy标记)
最新推荐文章于 2024-06-22 18:37:07 发布