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

正题

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


题目大意

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

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

强制在线

1≤n,m≤105,1≤ai,x≤1091\leq n,m\leq 10^5,1\leq a_i,x\leq 10^{9}1n,m105,1ai,x109

操作111的个数不超过650006500065000


解题思路

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

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

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

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

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

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

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

时间复杂度:O(nn)O(n\sqrt n)O(nn)


code

#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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317425.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C. The Sports Festival

C. The Sports Festival 题意&#xff1a; n个数&#xff0c;依次将所有数加入到区间内&#xff0c;每次得到一个k&#xff0c;k等于当前区间的最大值减最小值&#xff0c; 求所有k的和的最小值 题解&#xff1a; 一开始就没往dp那方面想&#xff0c;自己在dp这方面的理解还…

模板:点分治点分树

文章目录前言点分治背景解析代码点分树情境代码thanks for reading!所谓点分治&#xff0c;就是把所有的点分开来治 &#xff08;逃&#xff09; &#xff08;应广大观众要求&#xff0c;开篇废话改回原风格qwq&#xff09; 前言 很神奇的算法。 没有引入任何新的知识&#x…

.NET Core 3 Preview 2发布,C#8更强大的模式匹配

.NET Core 3 Preview 2 发布了&#xff0c;此版本主要带来了 C# 8 相关的新功能&#xff0c;C# 8 Preview 2 是 .NET Core 3 SDK 的一部分。C# 8 中使用模式进行更多操作&#xff0c;主要特性包括&#xff1a;using 声明改变需要缩进代码的方式&#xff0c;现在可以编写以下代码…

Loj#2474-「2018 集训队互测 Day 3」北校门外的未来【LCT】

正题 题目链接:https://loj.ac/p/2474 题目大意 开始有一个只有点111的图&#xff0c;一个点xxx能走到点yyy当且仅当路径(x,y)(x,y)(x,y)之间&#xff08;不包括x,yx,yx,y&#xff09;不存在编号比xxx或yyy要大的节点。有mmm次操作&#xff1a; 新建一个编号为yyy的节点和xx…

CF407 E. k-d-sequence(线段树+单调栈)

文章目录CF407 E. k-d-sequenceproblemsolutioncodeCF407 E. k-d-sequence problem solution special case&#xff0c;d0d0d0&#xff0c;相当于寻找最长的一段数字相同的区间 other case&#xff0c;如果要满足公差为ddd等差序列 区间内每个数在模ddd意义下同余每个数互不…

D. Binary Literature

D. Binary Literature 题意&#xff1a; 给三个长度为2 * n的01串&#xff0c;让你构造一个长度小于3 * n的字符串&#xff0c;使得这个串至少包含两个01串 题解&#xff1a; 很巧妙的构造题 三个指针分别指向三个串&#xff0c;因为是01串&#xff0c;所以一定存在两个字符…

安逸:鼠绘《诗与远方》

【作品名称】《诗与远方》【作者介绍】徐安&#xff08;笔名安逸&#xff0c;常州&#xff09;&#xff0c;PPT专家&#xff0c;鼠绘专家。平面设计专业&#xff0c;6年PPT设计经验&#xff1b;历届江苏省PPT制作大赛一等奖获得者&#xff0c;PA口袋动画重要合作人。PPT动画制作…

洛谷P4292:重建计划(点分治、单调队列)

解析 第一眼&#xff1a;Wow这么水的黑&#xff1f;&#xff1f; 然后写了一发二分套线段树的3log代码上去 T到飞起&#xff0c;只有40… 无奈瞅了一眼标签&#xff1a;单调队列 对啊 于是又写了一个上去 20 … 好啊 然后就摆烂了 qwq 果然黑题没有一个好东西 一个关键的思…

E. Colorings and Dominoes(未解决)

E. Colorings and Dominoes 题意&#xff1a; n * m的格子&#xff0c;分为黑白格子&#xff0c;白格子可以染成蓝色或者红色&#xff0c;一个1 * 2的多米诺骨牌&#xff0c;可以覆盖两个连续的水平的红色格子或者两个连续的竖着的蓝色格子&#xff0c;对于一个染色方案&…

[HNOI2016]网络(树链剖分+线段树+大根堆)

[HNOI2016]网络 problem solution 另辟蹊径&#xff0c;不把交互请求赋在新增路径上&#xff0c;反而把交互请求赋在树上除去该请求路径覆盖点的其它点上 显然&#xff0c;路径问题树剖是非常可以的、 那么一个点上的信息就表示所有不经过该点的交互请求&#xff0c;用堆…

P4557-[JSOI2018]战争【凸包,闵可夫斯基和】

正题 题目连接:https://www.luogu.com.cn/problem/P4557 题目大意 给出两个点集A,BA,BA,B&#xff0c;qqq次询问给出一个向量vvv&#xff0c;询问将BBB中所有点加上向量vvv后两个集合的凸包是否有交。 1≤n,m,q≤1051\leq n,m,q\leq 10^51≤n,m,q≤105 解题思路 闵可夫斯基和…

IdentityServer4实战 - JWT Token Issuer 详解

一.前言本文为系列补坑之作&#xff0c;拖了许久决定先把坑填完。下文演示所用代码采用的 IdentityServer4 版本为 2.3.0&#xff0c;由于时间推移可能以后的版本会有一些改动&#xff0c;请参考查看&#xff0c;文末附上Demo代码。本文所诉Token如无特殊说明皆为 JWT Token。众…

P3834 【模板】可持久化线段树 2(整体二分做法)

P3834 【模板】可持久化线段树 2&#xff08;主席树&#xff09; 我们详细讲讲这个整体二分如何求区间第k小 我们都知道二分可以求出区间里某个想要的值&#xff0c;如果有很多询问&#xff0c;我们对每个询问都进行二分&#xff0c;复杂度就是O(QNlog(1e9))铁超&#xff0c;那…

YBTOJ洛谷P3292:幸运数字(线性基、点分治/倍增)

解析 虽然使用三个log的倍增算法艹过去了 但是我们还是来聊聊正解吧 考虑点分治 对于当前的根&#xff0c;dfs求出联通块内每个点到当前根的线性基 一条路径的答案应该在路径出现上第一个成为根的点时统计到 具体来说&#xff0c;就是路径的两端点在同一个solve函数的不同子树…

AGC053E-More Peaks More Fun【计数】

正题 题目链接:https://atcoder.jp/contests/agc053/tasks/agc053_e 题目大意 给出nnn个二元组(ai,bi)(a_i,b_i)(ai​,bi​)&#xff0c;求有多少个1∼n1\sim n1∼n的排列ppp满足&#xff1a; 你可以将一些(ai,bi)(a_i,b_i)(ai​,bi​)变为(bi,ai)(b_i,a_i)(bi​,ai​)定义序…

「JOISC 2020 Day4」治疗计划(线段树+dijkstra最短路)

「JOISC 2020 Day4」治疗计划 description solution 设dpi:1−Ridp_i:1-R_idpi​:1−Ri​ 都能被救治成功的最小花费 两个治疗方案[Li,Ri],[Lj,Rj][L_i,R_i],[L_j,R_j][Li​,Ri​],[Lj​,Rj​]能够合并成完整的健康区间的条件为Ri−Lj1≥∣Ti−Tj∣R_i-Lj1\ge |T_i-T_j|Ri​…

胡浩:人人能学的AI《从零开始机器学习》苏州.NET俱乐部课程分享

【课程名称】《从零开始机器学XI》【老师介绍】胡浩&#xff0c;微软最有价值专家&#xff08;MVP&#xff0c;十余届多方向&#xff09;&#xff0c;微软技术大会讲师。云、数据中心基础架构、全栈虚拟化、企业移动管理等领域的架构师及顾问。AI/ML等新技术的爱好者&#xff0…

整体二分例题

参考oi wiki 引入&#xff1a; 有一部分题可以使用二分的办法来解决。但是当这种题目有多次询问且每次询问我们对每个查询都直接二分&#xff0c;可能会收获一个 TLE。这时候我们就会用到整体二分。整体二分的主体思路就是把多个查询一起解决。&#xff08;所以这是一个离线算…

P8338-[AHOI2022]排列【质因数分解】

正题 题目链接:https://www.luogu.com.cn/problem/P8338 题目大意 给出一个排列pip_ipi​&#xff0c;定义ai0i,aikapik−1a_i^0i,a_i^ka_{p_i}^{k-1}ai0​i,aik​api​k−1​。 对于排列PPP&#xff0c;定义F(P)F(P)F(P)表示最小的一个正整数kkk满足Pk1PP^{k1}PPk1P。 定义…

CF1100F Ivan and Burgers(线性基)

解析 做幸运数字的时候逛题解区爬过来的 挺妙的 把所有询问离线下来&#xff0c;按右端点排序 贪心的让最高位更高的向量出现的尽可能向右 实现上可以把线性基里的向量和当前的数swap来实现 代码就非常好写了 代码 #include<bits/stdc.h> using namespace std; #defi…