題目鏈接
題意
- 就是給你一個長度爲n數組以及n個區間[li,ri],然後f(i)定義爲區間[li,ri]的和,然後兩種操作,一個是單點改值,另一個是查詢∑i=lrf(i)
題解
- 分塊套路題,和BZOJ4765差不多,將n個區間分塊,預處理出數組中的每一個數對每一個塊的影響個數,維護每個塊的f(i)總和,然後改值的時候對所有的n個塊暴力更新塊的f(i)總和,然後查詢的時候對於整塊O(1)得到答案,非整塊用樹狀數組暴力查詢
- 注意可能爆long long,可還行
複雜度
- O(nnlogn)
代碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int smaxn=400;
int n,q,l[maxn],r[maxn],opt,u,v,b[maxn];
namespace bit{
unsigned long long s[maxn];
int lowbit(int x) {return x&(-x);}
void add(int id,int val){
for(int i=id;i<=n;i+=lowbit(i)){
s[i]+=val;
}
}
unsigned long long query(int id){
unsigned long long ans=0;
for(int i=id;i>=1;i-=lowbit(i)){
ans+=s[i];
}
return ans;
}
unsigned long long qsum(int l,int r){return query(r)-query(l-1);}
void clear(){memset(s,0,sizeof(s));}
}
using namespace bit;
namespace blocking{
int tot,belong[maxn],siz[smaxn],block;
unsigned long long sum[maxn];
int a[maxn],f[maxn][smaxn],c[maxn];
void init(int n) {
block=(int)sqrt((double)n);
tot=n%block?(n/block+1):(n/block);
for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
for(int i=1;i<=tot;i++) siz[i]=(min(i*block,n)-(i-1)*block);
for(int i=1;i<=tot;i++) {
for(int j=1;j<=n;j++) c[j]=0;
for(int j=block*(i-1)+1;j<=min(i*block,n);j++) c[l[j]]++,c[r[j]+1]--;
for(int j=1;j<=n;j++) c[j]+=c[j-1],f[j][i]=c[j];
}
}
void update(int id,int val) {
add(id,val-a[id]);
for(int i=1;i<=tot;i++) sum[i]+=1LL*f[id][i]*(val-a[id]);
a[id]=val;
}
unsigned long long query(int u,int v) {
unsigned long long ans=0;
if(belong[v]-belong[u]<=1) {
for(int i=u;i<=v;i++) ans+=qsum(l[i],r[i]);
return ans;
}
for(int i=u;i<=belong[u]*block;i++) ans+=qsum(l[i],r[i]);
for(int i=belong[u]+1;i<=belong[v]-1;i++) ans+=sum[i];
for(int i=(belong[v]-1)*block+1;i<=v;i++) ans+=qsum(l[i],r[i]);
return ans;
}
void debug() {
printf("block= %d, tot= %d\n",block,tot);
for(int i=1;i<=n;i++) printf("%d%c",belong[i],i==n?'\n':' ');
}
}
using namespace blocking;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
for(int i=1;i<=n;i++) scanf("%d %d",&l[i],&r[i]);
init(n);
for(int i=1;i<=n;i++) update(i,b[i]);
scanf("%d",&q);
while(q--) {
scanf("%d %d %d",&opt,&u,&v);
if(opt==2) printf("%llu\n",query(u,v));
else update(u,v);
}
}