题目链接:https://ac.nowcoder.com/acm/contest/917/J
题解链接:https://ac.nowcoder.com/discuss/198506?type=101&order=0&pos=11&page=1
答案式子转化为:
主要是这个多项和的平方的式子:
由这个式子可以得到:
用线段树搞一下
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
#define lson rt << 1,l,mid
#define rson rt << 1 | 1,mid + 1,r
#define pll pair<long,long>
long long sum[maxn << 2],val[maxn << 2],add[maxn << 2],a[maxn];
int n,q;
void pushdown(int rt,int len) {
if(!add[rt]) return ;
int left_len = (len + 1) / 2;
int right_len = len / 2;
int ls = rt << 1,rs = rt << 1 | 1;
val[ls] += add[rt] * add[rt] * left_len + 2 * add[rt] * sum[ls];
val[rs] += add[rt] * add[rt] * right_len + 2 * add[rt] * sum[rs];
sum[ls] += add[rt] * left_len;
sum[rs] += add[rt] * right_len;
add[ls] += add[rt];
add[rs] += add[rt];
add[rt] = 0;
}
void pushup(int rt) {
val[rt] = val[rt << 1] + val[rt << 1 | 1];
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void update(long long v,int li,int ri,int rt,int l,int r) {
if(li <= l && r <= ri) {
val[rt] += v * v * (r - l + 1) + 2 * v * sum[rt];
sum[rt] += (r - l + 1) * v;
add[rt] += v;
return ;
}
pushdown(rt,r - l + 1);
int mid = l + r >> 1;
if(li <= mid) update(v,li,ri,lson);
if(ri >= mid + 1) update(v,li,ri,rson);
pushup(rt);
}
long long query(int li,int ri,int rt,int l,int r) {
if(li <= l && r <= ri)
return sum[rt];
pushdown(rt,r - l + 1);
int mid = l + r >> 1;
long long ans = 0;
if(li <= mid) ans += query(li,ri,lson);
if(mid + 1 <= ri) ans += query(li,ri,rson);
return ans;
}
long long ask(int li,int ri,int rt,int l,int r) {
if(li <= l && r <= ri)
return val[rt];
pushdown(rt,r - l + 1);
int mid = l + r >> 1;
long long ans = 0;
if(li <= mid) ans += ask(li,ri,lson);
if(mid + 1 <= ri) ans += ask(li,ri,rson);
return ans;
}
int main() {
scanf("%d%d",&n,&q);
for(int i = 1; i <= n; i++) {
scanf("%lld",&a[i]);
update(a[i],i,i,1,1,n);
}
int op,l,r;
long long v;
for(int i = 1; i <= q; i++) {
scanf("%d",&op);
if(op == 1) {
scanf("%d%d%lld",&l,&r,&v);
update(v,l,r,1,1,n);
}
else {
scanf("%d%d",&l,&r);
long long d = query(l,r,1,1,n);
long long dd = ask(l,r,1,1,n);
d *= d;
printf("%lld\n",(d - dd) / 2);
}
}
return 0;
}