P5113-Sabbat of the witch【分块,基数排序】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P5113


1|1题目大意

一个长度为n的序列am次要求支持以下操作

  1. 将区间[l,r]都变为x
  2. 询问区间[l,r]的和。
  3. 将第x次操作1撤销。

强制在线

1n,m105,1ai,x109

操作1的个数不超过65000


1|2解题思路

考虑分块,那么我们需要解决散块和整块的问题。

考虑使用领接表(单向链表)来维护每个数字和块的历史状态,那么对于散块来说我们直接添加新节点连接,然后撤回时给对应操作打上标记,再在邻接表上一直跳到没有打标记的节点即可。
在散块的个体处理完后我们需要重构维护整块信息。

现在主要是整块如何处理的问题,一般的我们会有一个ansi表示第i块的和,和同上面个体一样的,每个块都有一个领接表来表明它的历史状态。

对于一个块来说,不是整块修改产生贡献的部分个体的修改时间比整块的修改时间要晚,而且撤回操作只会让整个块的修改时间变早,而修改操作一定会让整个块的修改时间变成最晚的。

结合上面的性质,我们大概能得到一个做法。对于每个块,我们维护一个每个数散块的修改时间升序排序的序列,这样越在前面的数越容易被整块的修改影响。也就是必定是影响一个前缀,假设这个前缀的位置为x,那么撤回操作只会让x向前移动,而整块修改只会让x直接跳到R,这两种情况分开维护的话就会发现对于每次重构后的块,x最多移动n次,也就是这个移动的复杂度均摊进了重构中。

而这个升序序列只需要在散块修改的时候才需要重构,需要使用到基数排序。

需要注意的细节是开始所有数都没有被修改但是有值,所以块内的初值很重要。

时间复杂度:O(nn)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define ll long long using namespace std; const ll N=1e5+10,Q=320,P=256; ll n,m,tot,cnt,qnt,a[N],ls[N]; ll b[Q],rk[N],rks[N],res[N],xs[N]; ll w[N],ql[N],qr[N],val[N*Q],nxt[N*Q]; ll L[Q],R[Q],lst[Q],ans[Q],lp[Q],pos[N]; bool flag[N]; void Addl(ll &x,ll w) {val[++tot]=w;nxt[tot]=x;x=tot;return;} void PushUp(ll &x) {while(flag[val[x]])x=nxt[x];return;} void Rebuild(ll x){ for(ll i=0;i<P;i++)b[i]=0; for(ll i=L[x];i<=R[x];i++)b[val[ls[i]]%P]++; for(ll i=1;i<P;i++)b[i]+=b[i-1]; for(ll i=L[x];i<=R[x];i++) b[val[ls[i]]%P]--,rk[L[x]+b[val[ls[i]]%P]]=i; for(ll i=0;i<P;i++)b[i]=0; for(ll i=L[x];i<=R[x];i++)b[val[ls[i]]/P]++; for(ll i=1;i<P;i++)b[i]+=b[i-1]; for(ll i=R[x];i>=L[x];i--) b[val[ls[rk[i]]]/P]--,rks[L[x]+b[val[ls[rk[i]]]/P]]=rk[i]; for(ll i=L[x];i<=R[x];i++)xs[i]=val[ls[rks[i]]]; res[R[x]]=xs[R[x]]?w[xs[R[x]]]:a[rks[R[x]]]; for(ll i=R[x]-1;i>=L[x];i--) res[i]=res[i+1]+(xs[i]?w[xs[i]]:a[rks[i]]); lp[x]=L[x]; while(lp[x]<=R[x]&&xs[lp[x]]<val[lst[x]])lp[x]++; ans[x]=(lp[x]<=R[x])?res[lp[x]]:0; ans[x]+=(lp[x]-L[x])*w[val[lst[x]]]; return; } void Change(ll l,ll r,ll val){ ll x=pos[l],y=pos[r]; ++qnt;w[qnt]=val; ql[qnt]=l;qr[qnt]=r; if(x==y){ for(ll i=l;i<=r;i++) Addl(ls[i],qnt); Rebuild(x); return; } for(ll i=x+1;i<y;i++) Addl(lst[i],qnt),ans[i]=val*(R[i]-L[i]+1); for(ll i=l;i<=R[x];i++)Addl(ls[i],qnt); for(ll i=L[y];i<=r;i++)Addl(ls[i],qnt); Rebuild(x);Rebuild(y); return; } ll GetI(ll p){ if(!ls[p]&&!lst[pos[p]])return a[p]; return w[max(val[lst[pos[p]]],val[ls[p]])]; } ll Ask(ll l,ll r){ ll x=pos[l],y=pos[r],sum=0; if(x==y){ for(ll i=l;i<=r;i++)sum+=GetI(i); return sum; } for(ll i=x+1;i<y;i++)sum+=ans[i]; for(ll i=l;i<=R[x];i++)sum+=GetI(i); for(ll i=L[y];i<=r;i++)sum+=GetI(i); return sum; } void Remake(ll x){ if(!flag[val[lst[x]]])return; PushUp(lst[x]); if(xs[R[x]]<val[lst[x]]){ ans[x]=(R[x]-L[x]+1)*w[val[lst[x]]]; return; } lp[x]--; while(lp[x]>=L[x]&&xs[lp[x]]>=val[lst[x]])lp[x]--; lp[x]++;ans[x]=(lp[x]<=R[x])?res[lp[x]]:0; ans[x]+=(lp[x]-L[x])*w[val[lst[x]]]; return; } void Withdraw(ll p){ ll l=ql[p],r=qr[p];flag[p]=1; ll x=pos[l],y=pos[r]; if(x==y){ for(ll i=l;i<=r;i++)PushUp(ls[i]); Rebuild(x);return; } for(ll i=x+1;i<y;i++)Remake(i); for(ll i=l;i<=R[x];i++)PushUp(ls[i]); for(ll i=L[y];i<=r;i++)PushUp(ls[i]); Rebuild(x);Rebuild(y); return; } signed main() { // freopen("data.in","r",stdin); // freopen("data.out","w",stdout); scanf("%lld%lld",&n,&m); ll T=sqrt(n); for(ll i=1;i<=n/T;i++)L[i]=R[i-1]+1,R[i]=i*T; cnt=n/T;if(R[cnt]!=n)++cnt,L[cnt]=R[cnt-1]+1,R[cnt]=n; for(ll i=1;i<=cnt;i++) for(ll j=L[i];j<=R[i];j++)pos[j]=i; for(ll i=1;i<=n;i++)scanf("%lld",&a[i]),ans[pos[i]]+=a[i]; for(ll i=1;i<=cnt;i++)Rebuild(i); ll las=0; while(m--){ ll op;scanf("%lld",&op); if(op==1){ ll l,r,w; scanf("%lld%lld%lld",&l,&r,&w); l^=las;r^=las;Change(l,r,w); } else if(op==2){ ll l,r; scanf("%lld%lld",&l,&r); l^=las;r^=las; printf("%lld\n",las=Ask(l,r)); } else{ ll x;scanf("%lld",&x); x^=las;Withdraw(x); } } return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/16224137.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示