秒了一个 70 pts 做法,满分做法无外乎是用前缀和来去掉一个 log.
code:
#include <bits/stdc++.h> #define N 1000009 #define ll long long #define lson now<<1 #define rson now<<1|1 #define setIO(s) freopen(s".in","r",stdin) using namespace std; // 区间加 -> 线段树[l,r]区间,则贡献为[l,r]范围内所有节点 size*v,可以下传这个标记. int n,m; int lazy[N<<2],leaf[N<<2],len[N<<2]; ll si[N<<2],sum[N<<2],sumv[N<<2]; int A[N],dep[N<<2],maxdep; void build(int l,int r,int now) { len[now]=r-l+1; if(l==r) return; int mid=(l+r)>>1; dep[lson]=dep[now]+1,dep[rson]=dep[now]+1; build(l,mid,lson),build(mid+1,r,rson); } void pushup(int now) { si[now]=si[lson]+si[rson]+1ll*len[now]*leaf[now]; sumv[now]=sumv[lson]+sumv[rson]; sum[now]=sum[lson]+sum[rson]+1ll*sumv[now]*leaf[now]; } void dfs(int l,int r,int now) { if(l==r) { if(dep[now]==maxdep) si[now]=1,leaf[now]=1; else si[now]=2,leaf[now]=2; if(si[now]==1) sum[now]=A[l]; else sum[now]=A[l]*2; sumv[now]=A[l]; return; } int mid=(l+r)>>1; dfs(l,mid,lson),dfs(mid+1,r,rson); leaf[now]=leaf[lson]+leaf[rson]; pushup(now); } void mark(int now,ll v) { lazy[now]+=(int)v; sumv[now]+=1ll*v*len[now]; sum[now]+=1ll*v*si[now]; } void pushdown(int now) { if(lazy[now]) { mark(lson,lazy[now]); mark(rson,lazy[now]); lazy[now]=0; } } void update(int l,int r,int now,int L,int R,ll v) { if(l>=L&&r<=R) { mark(now,v); return; } int mid=(l+r)>>1; pushdown(now); if(L<=mid) update(l,mid,lson,L,R,v); if(R>mid) update(mid+1,r,rson,L,R,v); pushup(now); } char *p1,*p2,buf[100000]; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0,flag=1; char c; do { c=nc(); if(c=='-') flag=-1; }while(c<48); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*flag; } int main() { // setIO("input"); ll qaq; n=rd(),m=rd(),qaq=(ll)rd(); build(1,n,1); for(int i=1;i<(N<<2);++i) maxdep=max(dep[i],maxdep); for(int i=1;i<=n;++i) A[i]=rd(); dfs(1,n,1); ll dn=leaf[1]; ll gcd=__gcd(dn,qaq); dn/=gcd,qaq/=gcd; int x,y,z; for(int i=1;i<=m;++i) { x=rd(),y=rd(),z=rd(); update(1,n,1,x,y,1ll*z); ll tot=sum[1]; printf("%lld\n",tot/dn*qaq); } return 0; }