1 条题解
-
0
自动搬运
来自洛谷,原作者为

Rosyclouds
冷艳、高贵和理性的完美结合体搬运于
2025-08-24 22:23:15,当前版本为作者最后更新于2020-09-28 22:22:40,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
对楼上分块算法的代码补充
另提一下,之所以不会T,是因为我们当块大小>2S时才会重构,那么最多重构次,复杂度是
#include <bits/stdc++.h> using namespace std; #define LL long long #define ls p<<1 #define rs p<<1|1 const int M=2e5+5; int n,tot,Q,S,sz[450];//sz:块的大小 LL lazy[3][450],sum[450],num[450][900],tmp[M];//lazy:延迟更新标记 void Down(int p){ if(lazy[0][p]){ for(int i=1;i<=sz[p];++i)num[p][i]=lazy[0][p]; lazy[0][p]=0; } if(lazy[1][p]){ LL &x=lazy[1][p],&y=lazy[2][p]; for(int i=1;i<=sz[p];++i) num[p][i]+=x,x+=y; x=y=0; } } LL Query(int l,int r){ LL res=0; int k=1,id=0,t=1; while(k+sz[id]<=l)k+=sz[id++]; Down(id); while(k<l)++k,++t; while(t<=sz[id]&&k<=r)res+=num[id][t++],++k; ++id; while(k+sz[id]<=r)k+=sz[id],res+=sum[id++]; t=1;Down(id); while(k<=r)res+=num[id][t++],++k; return res; } void Change(int l,int r,int x){ int k=1,id=0,t=1; while(k+sz[id]<=l)k+=sz[id++]; Down(id); while(k<l)++k,++t; while(t<=sz[id]&&k<=r) sum[id]+=x-num[id][t],num[id][t++]=x,++k; ++id; while(k+sz[id]<=r){ k+=sz[id]; sum[id]=1ll*sz[id]*x; lazy[0][id]=x;lazy[1][id]=lazy[2][id]=0; id++; } t=1;Down(id); while(k<=r){ sum[id]+=x-num[id][t],num[id][t++]=x,++k; } return ; } void Update(int l,int r,int x){ int k=1,id=0,t=1; LL v=x; while(k+sz[id]<=l)k+=sz[id++]; Down(id); while(k<l)++k,++t; while(t<=sz[id]&&k<=r) sum[id]+=v,num[id][t++]+=v,++k,v+=x; ++id; while(k+sz[id]<=r){ k+=sz[id]; sum[id]+=(v+v+(1ll*sz[id]-1)*x)*sz[id]/2; lazy[1][id]+=v;lazy[2][id]+=x; v+=1ll*sz[id]*x;id++; } t=1;Down(id); while(k<=r){ sum[id]+=v,num[id][t++]+=v,++k,v+=x; } return ; } void Rebuild(){//块重构 tot=0; for(int i=0;sz[i];++i){ Down(i); for(int j=1;j<=sz[i];++j) tmp[++tot]=num[i][j]; sz[i]=sum[i]=0; } S=max(2,(int)sqrt(tot)); for(int i=1;i<=tot;++i){ int id=i/S; sum[id]+=tmp[i]; num[id][++sz[id]]=tmp[i]; } } void Insert(int x,int y){ int k=1,id=0,t=1; while(sz[id]&&k+sz[id]<=x)k+=sz[id++]; Down(id); while(k<x)++k,++t; for(int i=sz[id];i>=t;--i)num[id][i+1]=num[id][i]; num[id][t]=y,sum[id]+=y,++sz[id]; if(sz[id]>2*S)Rebuild(); //当块的大小超出2S的时候将所有块重构 } int main(){ int x,y,z,kind; scanf("%d%d",&n,&Q); int S=max(2,(int)sqrt(n)); for(int i=1;i<=n;++i){ scanf("%d",&x); int id=i/S; num[id][++sz[id]]=x; sum[id]+=x; } while(Q--){ scanf("%d%d%d",&kind,&x,&y); if(kind==1){ scanf("%d",&z); Change(x,y,z); } else if(kind==2){ scanf("%d",&z); Update(x,y,z); } else if(kind==3) Insert(x,y); else printf("%lld\n",Query(x,y)); } return 0; }
- 1
信息
- ID
- 5714
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者