1. 程式人生 > >【XSY2111】Chef and Churus 分塊 樹狀數組

【XSY2111】Chef and Churus 分塊 樹狀數組

ace open display 區間 IT log pair unsigned memset

題目描述

  有一個長度為\(n\)的數組\(A\)\(n\)個區間\([l_i,r_i]\),有\(q\)次操作:

   \(1~x~y\):把\(a_x\)改成\(y\)

   \(2~x~y\):求第\(l\)個區間到第\(r\)個區間的區間和的和。

  \(n,q\leq {10}^5,a_i\leq {10}^9\)

題解

  分塊。

  設\(s_i\)為第\(i\)塊的所有區間的區間和,\(d_{i,j}\)為第\(i\)塊有多少個區間包含了\(j\)這個位置。

  修改時修改樹狀數組和每個區間的區間和。設當前\(a_x=v\),則\(s_i+=(y-v)\times d_{i,x}\)

  查詢時完整的區間直接查詢區間和,不完整的區間就暴力查詢。

  設塊大小為\(m\),時間復雜度為
\[ T(n)=O(\frac{n}{m}+m\log n) \]
  當\(m=\sqrt{\frac{n}{\log n}}\)
\[ T(n)_{\min}=O(n\sqrt{n\log n}) \]

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; ull c[100010]; int a[100010]; int n; void add(int x,ull v) { for(;x<=n;x+=x&-x) c[x]+=v; } ull sum(int x) { ull s=0; for(;x;x-=x&-x) s+=c[x]; return s; } int
bl; ull s[1010]; int d[1010][100010]; int l[100010]; int r[100010]; int block[100010]; int left[100010]; int right[100010]; int main() { memset(c,0,sizeof c); // freopen("xsy2111.in","r",stdin); // freopen("xsy2111.out","w",stdout); int m; scanf("%d",&n); int i; for(i=1;i<=n;i++) { scanf("%d",&a[i]); add(i,a[i]); } bl=100; m=(n+bl-1)/bl; for(i=1;i<=n;i++) block[i]=(i+bl-1)/bl; for(i=1;i<=m;i++) { left[i]=(i-1)*bl+1; right[i]=min(i*bl,n); } for(i=1;i<=n;i++) { scanf("%d%d",&l[i],&r[i]); s[block[i]]+=sum(r[i])-sum(l[i]-1); d[block[i]][l[i]]++; if(r[i]<n) d[block[i]][r[i]+1]--; } int j; for(i=1;i<=m;i++) for(j=2;j<=n;j++) d[i][j]+=d[i][j-1]; int q; scanf("%d",&q); int op,x,y,k; for(i=1;i<=q;i++) { scanf("%d%d%d",&op,&x,&y); if(op==1) { int v=a[x]; for(j=1;j<=m;j++) s[j]+=ull(y-v)*d[j][x]; add(x,y-v); a[x]=y; } else { ull ans=0; for(j=block[x];j<=block[y];j++) if(left[j]>=x&&right[j]<=y) ans+=s[j]; else { int mi=max(left[j],x); int mx=min(right[j],y); for(k=mi;k<=mx;k++) ans+=sum(r[k])-sum(l[k]-1); } printf("%llu\n",ans); } } return 0; }

【XSY2111】Chef and Churus 分塊 樹狀數組