题意:长度为n的序列a,现在有n个函数f,第i个函数f[i]的值为(a[l[i]]+a[l[i]+1]...a[r[i]]).Q个操作
操作1:修改a[i]的值.
操作2:求f[l]+f[l+1]+..f[r]的值.
n,Q<=1e5.a[i]<=1e9.
可以用BIT O(logn)内求出一个f[i]的值 查询一次要O(nlogn) 总共O(Q*nlogn) TLE....
现在能在O(logn)内求出一个f[i].考虑对序列f进行分块.
用差分对每一块进行预处理,处理出这一块中每个a[i]出现的次数,同时维护该块的f[i]之和.
对于修改 知道序列a中第p个位置在该块的出现次数,容易更新出该块f[i]之和 O(sqrt(n)).
对于查询,头尾两个非整块BIT暴力求出f[i] 中间块O(1)累加.O(sqrt(n)*logn+sqrt(n)).
操作1:修改a[i]的值.
操作2:求f[l]+f[l+1]+..f[r]的值.
n,Q<=1e5.a[i]<=1e9.
可以用BIT O(logn)内求出一个f[i]的值 查询一次要O(nlogn) 总共O(Q*nlogn) TLE....
现在能在O(logn)内求出一个f[i].考虑对序列f进行分块.
用差分对每一块进行预处理,处理出这一块中每个a[i]出现的次数,同时维护该块的f[i]之和.
对于修改 知道序列a中第p个位置在该块的出现次数,容易更新出该块f[i]之和 O(sqrt(n)).
对于查询,头尾两个非整块BIT暴力求出f[i] 中间块O(1)累加.O(sqrt(n)*logn+sqrt(n)).
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=450;
ll m,n,num,Q,L[N],R[N],c[N],pos[N];
ll a[N];
unsigned long long val[N],b[N],cnt[M][N];
int lowbit(int x)
{
return x&-x;
}
void update(int x,ll val)
{
for(int i=x;i<N;i+=lowbit(i))
b[i]+=val;
}
ll sum(int x)
{
ll res=0;
for(int i=x;i>0;i-=lowbit(i))
res+=b[i];
return res;
}
void init()
{
m=(int)sqrt(n);
num=n/m;
if(n%m)
num++;
for(int i=1;i<=n;i++)
pos[i]=(i-1)/m+1;
for(int i=1;i<=num;i++)
{
memset(c,0,sizeof(c));
for(int j=(i-1)*m+1;j<=i*m&&j<=n;j++)
{
c[L[j]]++;
c[R[j]+1]--;
}
for(int k=1;k<=n;k++)
c[k]+=c[k-1],cnt[i][k]=c[k],val[i]+=c[k]*a[k];
}
}
ll ask(int l,int r)
{
ll res=0;
if(pos[l]==pos[r])
{
for(int i=l;i<=r;i++)
res+=sum(R[i])-sum(L[i]-1);
}
else
{
for(int i=l;i<=pos[l]*m;i++)
res+=sum(R[i])-sum(L[i]-1);
for(int i=(pos[r]-1)*m+1;i<=r;i++)
res+=sum(R[i])-sum(L[i]-1);
}
for(int i=pos[l]+1;i<pos[r];i++)
res+=val[i];
return res;
}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]),update(i,a[i]);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&L[i],&R[i]);
init();
scanf("%lld",&Q);
ll op,l,r,p,x;
while(Q--)
{
scanf("%lld",&op);
if(op==1)
{
scanf("%lld%lld",&p,&x);
for(int i=1;i<=num;i++)
{
ll t=cnt[i][p];
val[i]=val[i]+t*(x-a[p]);
}
update(p,x-a[p]);
a[p]=x;
}
else
{
scanf("%lld%lld",&l,&r);
printf("%llu\n",ask(l,r));
}
}
return 0;
}