题面
给定长度为N的数列,输入Q个操作
C l r d:数列第l~r个数都加d
Q l r:输出数列l~r个数的和
N<=105 Q<=105
分析
noip要来了,多打暴力呀!于是,分块模板
代码
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- using namespace std;
- #define N 100010
- #define ll long long
- ll n,m;
- char op[3];
- ll a[N],sum[N],add[N],L[N],R[N],pos[N];
- void update(ll l,ll r,ll v)
- {
- ll p=pos[l],q=pos[r];
- if(p==q)
- {
- for(ll i=l;i<=r;i++)a[i]+=v;
- sum[p]+=v*(r-l+1);
- }
- else
- {
- for(ll i=p+1;i<=q-1;i++)add[i]+=v;
- for(ll i=l;i<=R[p];i++)a[i]+=v;
- sum[p]+=v*(R[p]-l+1);
- for(ll i=L[q];i<=r;i++)a[i]+=v;
- sum[q]+=v*(r-L[q]+1);
- }
- }
- ll query(ll l,ll r)
- {
- ll p=pos[l],q=pos[r],ret=0;
- if(p==q)
- {
- for(ll i=l;i<=r;i++)ret+=a[i];
- ret+=add[p]*(r-l+1);
- }
- else
- {
- for(ll i=p+1;i<=q-1;i++)ret+=sum[i]+(R[i]-L[i]+1)*add[i];
- for(ll i=l;i<=R[p];i++)ret+=a[i];
- ret+=add[p]*(R[p]-l+1);
- for(ll i=L[q];i<=r;i++)ret+=a[i];
- ret+=add[q]*(r-L[q]+1);
- }
- return ret;
- }
- int main()
- {
- scanf("%lld%lld",&n,&m);
- for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);
- int t=sqrt(n);
- for(ll i=1;i<=t;i++)L[i]=(i-1)*t+1,R[i]=i*t;
- if(R[t]<n)t++,L[t]=R[t-1]+1,R[t]=n;
- for(ll i=1;i<=t;i++)
- for(ll j=L[i];j<=R[i];j++)
- pos[j]=i,sum[i]+=a[j];
- while(m--)
- {
- ll l,r,d;
- scanf("%s%lld%lld",op,&l,&r);
- if(op[0]=='C')scanf("%lld",&d),update(l,r,d);
- else printf("%lld ",query(l,r));
- }
- }