#K-D Tree#BZOJ 4303 数列
分析
将 \((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;
}