链接: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个电极插头,每个插头有一个信号aiai,
小T可以使在区间[ l,r ][ l,r ]内的所有信号加上一个值k。
对于区间[ l,r ][ l,r ]的信号强度有一个计算公式:
我们定义
f(k)=ak×∑rj=k+1ajf(k)=ak×∑j=k+1raj
则信号强度就为:
∑ri=lf(i)∑i=lrf(i)
你可以认为f(i)就是第i个插头的信号强度。
现在小T一会儿修改信号值,一会儿询问信号强度,你是数据库的管理员,为了不被小TD,所以你要告诉他信号强度是多少。
注:本系列题不按难度排序哦
输入描述:
第一行两个整数n,Q
第二行n个整数代表a
后Q行代表操作:
一操作:1 l r x1 l r x代表区间[ l,r ][ l,r ]加x。
二操作:2 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 long范围内(如果你不相信,可以写高精)。
时空限制为标程的5倍,放心卡常。
备注:
100% 1≤n,Q≤105100% 1≤n,Q≤105
对于所有ai≤100ai≤100
不会写看题解:
透过这道题 我学会了如何用线段数维护每一位的数的平方 的区间和。 也知道了如果是区间内任意两个数相乘之和的答案是这样求得。很不错得一道题,学到了学到了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll c1[N*4],c2[N*4],a[N],lazy[N*4];
int n,m;
void build(int id,int l,int r)
{
if(l==r)
{
ll x;
scanf("%lld",&x);
c1[id]=x;
c2[id]=x*x;
return ;
}
int mid=l+r>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
c1[id]=c1[id<<1]+c1[id<<1|1];
c2[id]=c2[id<<1]+c2[id<<1|1];
}
void pushdown(int id,int l,int r)
{
if(lazy[id])
{
int mid=l+r>>1;
int l1=mid-l+1;
int l2=r-mid;
c2[id<<1]+=l1*lazy[id]*lazy[id]+2*c1[id<<1]*lazy[id];
c2[id<<1|1]+=l2*lazy[id]*lazy[id]+2*c1[id<<1|1]*lazy[id];
c1[id<<1]+=l1*lazy[id];
c1[id<<1|1]+=l2*lazy[id];
lazy[id<<1]+=lazy[id];
lazy[id<<1|1]+=lazy[id];
lazy[id]=0;
}
}
void up(int id,int l,int r,int ql,int qr,ll val)
{
if(ql<=l&&r<=qr)
{
int len=r-l+1;
c2[id]+=val*val*len+2*c1[id]*val;
c1[id]+=val*len;
lazy[id]+=val;
return ;
}
pushdown(id,l,r);
int mid=l+r>>1;
if(ql<=mid) up(id<<1,l,mid,ql,qr,val);
if(qr>mid) up(id<<1|1,mid+1,r,ql,qr,val);
c1[id]=c1[id<<1]+c1[id<<1|1];
c2[id]=c2[id<<1]+c2[id<<1|1];
}
ll qu(int id,int l,int r,int ql,int qr,int op)
{
if(ql<=l&&r<=qr)
{
if(op==1) return c1[id];
else return c2[id];
}
pushdown(id,l,r);
ll ans=0;
int mid=l+r>>1;
if(ql<=mid) ans+=qu(id<<1,l,mid,ql,qr,op);
if(qr>mid) ans+=qu(id<<1|1,mid+1,r,ql,qr,op);
return ans;
}
int main()
{
cin>>n>>m;
build(1,1,n);
for(int i=1;i<=m;++i)
{
int ty,l,r;
ll val;
scanf("%d%d%d",&ty,&l,&r);
if(ty==1)
{
scanf("%lld",&val);
up(1,1,n,l,r,val);
}
else
{
ll nu1=qu(1,1,n,l,r,1);
ll nu2=qu(1,1,n,l,r,2);
printf("%lld\n",(nu1*nu1-nu2)/2);
}
}
}