列表

详情


NC25879. 外挂

描述

我的就是我的,你也是我的,记住了,狐狸!
                                                                      ——韩信-白龙吟
对于打赌输了的小T会遭受到制裁,小s修改了数据库使他可以派出许多军队来围攻小T.
很不幸,小T与小s打赌打输了,现在小T遭受着枪林弹雨与十面埋伏,因为小T是神所以他决定要扭转局势。
他要修改数据库!
数据总库的信号墙有n个电极插头,每个插头有一个信号a_i,
小T可以使在区间内的所有信号加上一个值k。
对于区间的信号强度有一个计算公式:
我们定义

则信号强度就为:

你可以认为f(i)就是第i个插头的信号强度。
现在小T一会儿修改信号值,一会儿询问信号强度,你是数据库的管理员,为了不被小TD,所以你要告诉他信号强度是多少。

注:本系列题不按难度排序哦

输入描述

第一行两个整数n,Q
第二行n个整数代表a
后Q行代表操作:
一操作:代表区间加x。
二操作:代表区间询问。

输出描述

每一行一个数字,表示对于一个二操作的答案。

示例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\ long范围内(如果你不相信,可以写高精)。
时空限制为标程的5倍,放心卡常。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 285ms, 内存消耗: 8412K, 提交时间: 2019-06-15 11:23:35

#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);
		}
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 114ms, 内存消耗: 7544K, 提交时间: 2020-02-01 15:08:10

#include<bits/stdc++.h>
using namespace std;

long long a[100005],S1[400005],S2[400005];
long long s1,s2,y,T[400005]={0};
void build(int L,int R,int x)
{
	if(L==R)
	{
		S1[x]=a[L],S2[x]=a[L]*a[L];
		return;
	}
	int M=(L+R)>>1;
	build(L,M,2*x);
	build(M+1,R,2*x+1);
	S1[x]=S1[2*x]+S1[2*x+1];
	S2[x]=S2[2*x]+S2[2*x+1];
}
void down(int L,int R,int x)
{
	if(!T[x])return;
	int M=(L+R)>>1;
	T[2*x]+=T[x],T[2*x+1]+=T[x];
	S2[2*x]+=2*S1[2*x]*T[x]+T[x]*T[x]*(M-L+1);
	S2[2*x+1]+=2*S1[2*x+1]*T[x]+T[x]*T[x]*(R-M);
	S1[2*x]+=(M-L+1)*T[x];
	S1[2*x+1]+=(R-M)*T[x];
	T[x]=0;
}
void add(int L,int R,int l,int r,int x)
{
	if(l<=L&&R<=r)
	{
		T[x]+=y;
		S2[x]+=2*S1[x]*y+y*y*(R-L+1);
		S1[x]+=(R-L+1)*y;
		return;
	}
	down(L,R,x);
	int M=(L+R)>>1;
	if(M>=l)add(L,M,l,r,2*x);
	if(M<r)add(M+1,R,l,r,2*x+1);
	S1[x]=S1[2*x]+S1[2*x+1];
	S2[x]=S2[2*x]+S2[2*x+1];
}
void search(int L,int R,int l,int r,int x)
{
	if(l<=L&&R<=r)
	{
		s1+=S1[x],s2+=S2[x];
		return;
	}
	down(L,R,x);
	int M=(L+R)>>1;
	if(M>=l)search(L,M,l,r,2*x);
	if(M<r)search(M+1,R,l,r,2*x+1);
}
int main()
{
	int i,n,Q,f,l,r;
	scanf("%d%d",&n,&Q);
	for(i=1;i<=n;i++)scanf("%lld",&a[i]);
	build(1,n,1);
	while(Q--)
	{
		scanf("%d%d%d",&f,&l,&r);
		if(f==1)scanf("%lld",&y),add(1,n,l,r,1);
		else
		{
			s1=s2=0,search(1,n,l,r,1);
			printf("%lld\n",(s1*s1-s2)/2);
		}
	}
	return 0;
}

上一题