#K-D Tree#BZOJ 4303 數列
阿新 • • 發佈:2022-04-13
分析
將 \((i,p_i)\) 視為一個點,那麼相當於對橫座標或縱座標對應的點區間乘、區間加或者區間求和,
把這些點丟到 K-D Tree 上,維護最小/大橫/縱座標,如果當前區間點在範圍內直接打懶標記,否則暴力修改,時間複雜度 \(O(m\sqrt{n})\)
程式碼
#include <cstdio> #include <cctype> #include <algorithm> #include <queue> using namespace std; const int N=50011,lim=536870911; int ran,root,n,m; int iut(){ int ans=0; char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=ans*10+c-48,c=getchar(); return ans; } void print(int ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } int min(int a,int b){return a<b?a:b;} int max(int a,int b){return a>b?a:b;} struct rec{ int p[2],w; bool operator <(const rec &t)const{ return p[ran]<t.p[ran]; } }; struct KD_Tree{ int mn[N][2],mx[N][2],son[N][2],w[N],Lazy[N],lazy[N],len[N]; rec p[N]; void pup(int now){ for (int i=0;i<2;++i){ mn[now][i]=mx[now][i]=p[now].p[i]; if (son[now][0]){ mn[now][i]=min(mn[now][i],mn[son[now][0]][i]); mx[now][i]=max(mx[now][i],mx[son[now][0]][i]); } if (son[now][1]){ mn[now][i]=min(mn[now][i],mn[son[now][1]][i]); mx[now][i]=max(mx[now][i],mx[son[now][1]][i]); } } } void pLazy(int now,int z){ Lazy[now]=(1ll*Lazy[now]*z)&lim; lazy[now]=(1ll*lazy[now]*z)&lim; w[now]=(1ll*w[now]*z)&lim; p[now].w=(1ll*p[now].w*z)&lim; } void plazy(int now,int z){ lazy[now]=(lazy[now]+z)&lim; w[now]=(w[now]+1ll*z*len[now])&lim; p[now].w=(p[now].w+z)&lim; } int build(int l,int r,int Ran){ if (l>r) return 0; int mid=(l+r)>>1; ran=Ran,nth_element(p+l,p+mid,p+1+r); son[mid][0]=build(l,mid-1,Ran^1); son[mid][1]=build(mid+1,r,Ran^1); pup(mid),Lazy[mid]=1,len[mid]=r-l+1; return mid; } void update(int now,int l,int r,int x,int y,int opt){ if (r<mn[now][opt]||l>mx[now][opt]) return; if (l<=mn[now][opt]&&mx[now][opt]<=r){ pLazy(now,x),plazy(now,y); return; } if (Lazy[now]!=1){ if (son[now][0]) pLazy(son[now][0],Lazy[now]); if (son[now][1]) pLazy(son[now][1],Lazy[now]); Lazy[now]=1; } if (lazy[now]){ if (son[now][0]) plazy(son[now][0],lazy[now]); if (son[now][1]) plazy(son[now][1],lazy[now]); lazy[now]=0; } if (l<=p[now].p[opt]&&p[now].p[opt]<=r) p[now].w=(1ll*p[now].w*x+y)&lim; if (son[now][0]) update(son[now][0],l,r,x,y,opt); if (son[now][1]) update(son[now][1],l,r,x,y,opt); w[now]=(w[son[now][0]]+w[son[now][1]]+p[now].w)&lim; } int query(int now,int l,int r,int opt){ if (r<mn[now][opt]||l>mx[now][opt]) return 0; if (l<=mn[now][opt]&&mx[now][opt]<=r) return w[now]; if (Lazy[now]!=1){ if (son[now][0]) pLazy(son[now][0],Lazy[now]); if (son[now][1]) pLazy(son[now][1],Lazy[now]); Lazy[now]=1; } if (lazy[now]){ if (son[now][0]) plazy(son[now][0],lazy[now]); if (son[now][1]) plazy(son[now][1],lazy[now]); lazy[now]=0; } int ans=0; if (l<=p[now].p[opt]&&p[now].p[opt]<=r) ans+=p[now].w; if (son[now][0]) ans+=query(son[now][0],l,r,opt); if (son[now][1]) ans+=query(son[now][1],l,r,opt); return ans&lim; } }Tre; int main(){ n=iut(),m=iut(); for (int i=1;i<=n;++i) Tre.p[i]=(rec){i,iut(),0}; root=Tre.build(1,n,0); for (int i=1;i<=m;++i){ int opt=iut(),l=iut(),r=iut(); if (opt<2){ int x=iut(),y=iut(); Tre.update(root,l,r,x,y,opt); }else print(Tre.query(root,l,r,opt-2)),putchar(10); } return 0; }