蓝书(算法竞赛进阶指南)刷题记录——POJ3580 SuperMemo (Splay)

有效背单词的一个简单算法(一)——SugarMemo算法学习记录   看了著名的Palm上的背单词软件SugarMemo已经把源代码放出了 知道其中采用了国外的那个著名的SuperMemo的早先的一个算法(SM2)来记忆单词. 因为操作非常之简单,而且记忆效果也不错, 所以有想法把这个软件移植到PSP上,也是通过简单的几个键的操作方便对单词的记忆 现记录简要的过程如下: SugarMemo(我下面简称Sugar)的改进在于,通过一组测试,来 阅读详情

题目:POJ3580.
题目大意:给定一个长度为 n n n的序列,现在有 m m m次操作支持:
1.格式 A D D   x   y   v ADD\,x\,y\, v ADDxyv,表示给区间 [ x , y ] [x,y] [x,y]加上 v v v.
2.格式 R E V E R S E   x   y REVERSE\,x\,y REVERSExy,表示翻转区间 [ x , y ] [x,y] [x,y].
3.格式 R E V O L V E   x   y   k REVOLVE\,x\,y\,k REVOLVExyk,表示把区间 [ x , y ] [x,y] [x,y]旋转 k k k次.
4.格式 I N S E R T   x   y INSERT\,x\,y INSERTxy,表示在第 x x x个位置后面加上一个数字 y y y.
5.格式 D E L E T E   x DELETE\,x DELETEx,表示删除第 x x x个数字.
6.格式 M I N   x   y MIN\,x\,y MINxy,表示求区间 [ x , y ] [x,y] [x,y]的最小值.
1 ≤ n , m ≤ 1 0 5 1\leq n,m\leq 10^5 1≤n,m≤105.

一道数据结构裸题,很明显用平衡树来维护.

考虑将位置作为平衡树维护的键值,但是这个键值在插入删除时很难维护所以不存,每次查找一个位置通过平衡树上二分即可.

由于区间操作众多,所以Splay无疑是处理这道题最好的平衡树.

对于区间加,我们可以直接找到位置 x − 1 x-1 x−1和 y + 1 y+1 y+1所在的节点并把 x − 1 x-1 x−1 Splay到根 y + 1 y+1 y+1 Splay成 x − 1 x-1 x−1的儿子,那么 y + 1 y+1 y+1的右儿子就是整个区间,我们称之为提取区间,打上懒标记即可.

对于区间翻转,我们先提取出区间,很明显把提取出的区间中所有节点的左右儿子交换就可以做到翻转,维护懒标记即可.

对于区间旋转,容易发现它就是把区间 [ ( y − k + 1 )    m o d    ( y − x + 1 ) , y ] [(y-k+1)\,\,mod\,\,(y-x+1),y] [(y−k+1)mod(y−x+1),y]放到 x x x的前面,所以大力提取出区间并把表示区间的子树的根的父亲先设为空.之后大力提取区间 [ y , y − 1 ] [y,y-1] [y,y−1],把子树根的父亲设为 y y y即可.

对于插入,提取区间 [ x , x − 1 ] [x,x-1] [x,x−1]并在 x x x下面新建节点即可.

对于删除,提取区间 [ x , x ] [x,x] [x,x],把 x + 1 x+1 x+1的右儿子设为空即可.

对于区间最小值,直接提取区间输出最小即可.

时间复杂度 O ( n + m log ⁡ n ) O(n+m\log n) O(n+mlogn).

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
  using namespace std;
 
#define Abigail inline void
typedef long long LL;
 
const int N=100000,INF=(1<<31)-1;
//INF一定要开到2^31-1,不然会被卡
 
int n,a[N+9];
struct tree{
  int x,fa,s[2],siz,min,add,rev;
  tree(){x=fa=s[0]=s[1]=siz=add=rev=0;min=INF;}
  //构造函数,初始min=INF,为了避免Pushup时要判断儿子是否为空的情况
}tr[N*2+9];
int cn,rot,tmp[N*2+9],tt;
 
void Pushup(int k){
  int ls=tr[k].s[0],rs=tr[k].s[1];
  tr[k].siz=tr[ls].siz+tr[rs].siz+1;
  tr[k].min=min(tr[k].x,min(tr[ls].min,tr[rs].min));
}
 
void Update_rev(int k){if (!k) return;swap(tr[k].s[0],tr[k].s[1]);tr[k].rev^=1;}
void Update_add(int k,int v){if (!k) return;tr[k].add+=v;tr[k].x+=v;tr[k].min+=v;}
//建议要判掉k=0的情况不然可能会溢出

void Pushdown_rev(int k){
  if (!tr[k].rev) return;
  Update_rev(tr[k].s[0]);Update_rev(tr[k].s[1]);
  tr[k].rev=0;
}
 
void Pushdown_add(int k){
  if (!tr[k].add) return;
  Update_add(tr[k].s[0],tr[k].add);Update_add(tr[k].s[1],tr[k].add);
  tr[k].add=0;
}
 
void Pushdown(int k){Pushdown_rev(k);Pushdown_add(k);}
 
void Rotate(int x){
  int y=tr[x].fa,z=tr[y].fa,k=tr[y].s[1]==x;
  if (z) tr[z].s[tr[z].s[1]==y]=x;tr[x].fa=z;
  tr[y].s[k]=tr[x].s[k^1];if (tr[x].s[k^1]) tr[tr[x].s[k^1]].fa=y;
  tr[x].s[k^1]=y;tr[y].fa=x;
  Pushup(y);Pushup(x);
}
 
void Splay(int x,int go){
  tmp[tt=1]=x;
  for (int i=x;tr[i].fa;i=tr[i].fa) tmp[++tt]=tr[i].fa;
  for (;tt;--tt) Pushdown(tmp[tt]);
  for (int y,z;tr[x].fa^go;Rotate(x)){
    y=tr[x].fa;z=tr[y].fa;
    if (z^go) tr[z].s[0]==y^tr[y].s[0]==x?Rotate(x):Rotate(y);
    //一定要在这里写z^go而不是直接写z
  }
  if (!go) rot=x;
  Pushup(x);      //这道题虽然没卡,但这个Pushup有时候不写会出事
}
 
int New_node(int x,int fa){
  tr[++cn]=tree();
  tr[cn].x=tr[cn].min=x;tr[cn].siz=1;
  tr[cn].fa=fa;
  return cn;
}
 
void Build(int l,int r,int fa=0,int &k=rot){
  int mid=l+r>>1;
  k=New_node(a[mid],fa);
  if (l<mid) Build(l,mid-1,k,tr[k].s[0]);
  if (r>mid) Build(mid+1,r,k,tr[k].s[1]);
  Pushup(k);
}
 
int Find_rank(int p,int rot=rot){
  ++p;
  int k=rot;
  while (2333){
    Pushdown_rev(k);
    //翻转标记会改变树的形态,在查询第k个位置时一定要下传翻转标记
    if (p>tr[tr[k].s[0]].siz+1) p-=tr[tr[k].s[0]].siz+1,k=tr[k].s[1];
    else if (p<=tr[tr[k].s[0]].siz) k=tr[k].s[0];
      else break;
  }
  Splay(k,0);
  return k;
}
 
int Insert(int p,int x){
  int l=Find_rank(p),r=Find_rank(p+1);
  Splay(l,0);Splay(r,l);
  tr[r].s[0]=New_node(x,r);
  Splay(tr[r].s[0],0);
  return 0;
}
 
int Extract(int L,int R){
  int l=Find_rank(L-1),r=Find_rank(R+1);
  Splay(l,0);Splay(r,l);
  return tr[r].s[0];
}
 
void Erase(int p){int k=tr[Extract(p,p)].fa;tr[k].s[0]=0;Splay(k,0);}
void Change_add(int L,int R,int v){int k=Extract(L,R);Update_add(k,v);Splay(k,0);}
void Change_rev(int L,int R){int k=Extract(L,R);Update_rev(k);Splay(k,0);}
int Query_min(int L,int R){int k=Extract(L,R),res=tr[k].min;Splay(k,0);return res;}
 
void Change_spin(int L,int R,int x){
  x%=(R-L+1);
  if (!x) return;
  int l=Find_rank(L-1),r=Find_rank(L),t=Extract(R-x+1,R);
  tr[tr[t].fa].s[0]=0;Splay(tr[t].fa,0);
  Splay(l,0);Splay(r,l);
  tr[r].s[0]=t;tr[t].fa=r;
  Splay(t,0);
}
 
Abigail into(){
  scanf("%d",&n);
  for (int i=1;i<=n;++i)
    scanf("%d",&a[i]);
}
 
Abigail work(){
  Build(0,n+1);
}
 
Abigail getans(){
  char c[10];
  int q,x,y,z;
  scanf("%d",&q);
  while (q--){
    scanf("%s",c);
    switch (c[0]){
      case 'A':
        scanf("%d%d%d",&x,&y,&z);
        Change_add(x,y,z);
        break;
      case 'R':
        if (c[3]=='E'){
          scanf("%d%d",&x,&y);
          Change_rev(x,y);
        }else{
          scanf("%d%d%d",&x,&y,&z);
          Change_spin(x,y,z);
        }
        break;
      case 'I':
        scanf("%d%d",&x,&y);
        Insert(x,y);
        break;
      case 'D':
        scanf("%d",&x);
        Erase(x);
        break;
      case 'M':
        scanf("%d%d",&x,&y);
        printf("%d\n",Query_min(x,y));
        break;
    }
  }
}
 
int main(){
  into();
  work();
  getans();
  return 0;
}
supermemo::student: SuperMemo 2 (SM2) 算法的 JavaScriptTypeScript 实现,用于基于间隔的重复抽认卡 超级备忘录 (SM2) 算法的 JavaScript/TypeScript 实现,用于基于间隔的重复抽认卡。 如果您喜欢这个项目,请点击Star按钮 :star: 解释 type SuperMemoItem = { interval : number ; repetition : number ; efactor : number ; } ; type SuperMemoGrade = 0 | 1 | 2 | 3 | 4 | 5 ; supermemo ( item : SuperMemoItem , grade : SuperMemoGrade ) : SuperMemoItem 物品 重复:连续正确响应的数量。 初始repetition值应为0 。 interval :重复后的重复间隔(以天为单位)。 初始interval值应为0 。 efactor :易用性因子,反映 立即下载

相关推荐

PostgreSQL使用 pg_rman物理备份搭建流复制备库(streaming replication standby)

摘要:使用pg_rman备份搭建PostgreSQL流复制备库 本文详细介绍了利用pg_rman工具快速搭建PostgreSQL流复制备库的完整流程。该方法结合物理备份的高效性和流复制的实时性,特别适合大型数据库环境。主要内容包括:主库上的pg_rman安装配置、全量备份操作;备份文件传输至备库;备库数据目录准备及恢复;流复制参数配置;以及最终的启动验证步骤。文章还提供了架构示意图和关键配置示例,并包含常见问题排查建议,如备库无法启动或复制卡顿情况的处理方法。整个流程强调通过.pgpass文件管理密码的安全

liumangtuzi888的博客 1169

poj 3580 (splay 模板)

//本来用指针的那种写法,wa了20多次受不了了,看了一个大佬的博客,代码基本照抄,只不过将splay时pushdown(x)修该到Rotate里面#include &lt;iostream&gt;#include &lt;cstdio&gt;#include &lt;cstring&gt;#include &lt;algorithm&gt;using namespace std;const in...

kwahia的博客 314

4×V100部署Qwen3.8-Flash-Next:vLLM/GGUF实战

大模型本地部署的核心,是把参数量、量化精度、显存容量和推理框架放在同一张账本里算清楚。MoE 模型总参数量大但激活参数少,解码阶段更受显存带宽与 KV Cache 限制;通过 INT4/AWQ 或 GGUF 等 4-bit 量化可显著压缩权重占用,再结合 vLLM 张量并行、llama.cpp 分层切分提升多卡利用率。其技术价值在于让 V100 这类老架构 GPU 也能承载百亿级参数模型的私有化推理,并服务于 RAG 知识库、工作流 API、批量生成等场景。这次围绕 4×V100 32G 部署 Qwen3.

weixin_29061425的博客 352

poj3580:SuperMemo(块状链表/Splay)

传送门 题意: 题目要求实现一种数据结构,支持6种操作: add x,y D:第x个数到第y个数之间的数每个加D; reverse x y:第x个数到第y个数之间全部数翻转; revolve x y T:第x个数到第y个数之间的数,向后循环流动T次,即后面T个数变成这段子序列的最前面T个,前面的被挤到后面。 Insert x P:在第x个数后面插入一个数P。 Delete x:删除第x个数

DZYO的博客 491

nacos3.1.0适配国产数据库

Nacos 3.1.0适配国产数据库指南 本文介绍了Nacos 3.1.0版本适配达梦数据库和人大金仓数据库的具体步骤。主要内容包括:添加达梦和人大金仓的JDBC驱动依赖,修改nacos-persistence模块的配置文件及相关Java类,以及打包和运行注意事项。文章特别指出3.1.0版本需要JDK17环境,并提供了解决常见问题的建议,如添加VM options配置和不同启动方式等。通过本文的配置指导,可以实现Nacos服务在国产数据库环境下的正常运行。

梦昼初的博客 1467

第一节:Vben Admin介绍和初次运行

本文是【实战Vben Admin + Python】的第一节,本文内容主要是介绍Vben Admin框架和我们后端使用的技术,开发环境和工具的准备本节文章的目的是Vben Admin的简单介绍,通过配置可以让项目前端运行起来,由于项目默认开启了mock,展示的都是静态模拟数据,我们在此基础上,下一节将研究分析下Vben Admin的目录。为我们后端搭建准备。

cuiwin的专栏 7417

POJ 3580 SuperMemo(区间树)

唯一一个要说的就是REVOLVE操作。别的在笔记上有。 可以发现REVOLVE就是把一段区间砍下来然后接在一个点后面。 那么先把这个区间砍下来(rotateto(l-1,0)rotateto(r+1,root)),然后pushup,然后找到那个点(rotateto(x,0)rotateto(x+1,root)),然后插入回去。最后pushup。#include<iostream> #includ

Quack 661

微信公众平台 - 微信内置浏览器 WeixinJSBridge.invoke(‘xxx‘) API 报错:system:access_denied(常见于微信支付、分享朋友圈/转发好友等功能)解决方案

微信支付提示System:access_denied,调用微信支付返回:system:access_denied为什么,安卓版微信支付偶尔出现system:access_denied,微信公众号开发分享出现system:access_denied,system:access_denied如何解决?微信WeixinJSBridge.invoke(‘xxx‘)API调用后出现报错,微信内部H5WeixinJSBridge.invokesystem:access_denied,使用微信jssdk时报ac

🏆 前端领域优质创作者 5145

(POJ) 3580 SuperMemo

传送门 一道很全的splay模板题,自己搞了半天都不对,只能考别人的代码感受一下AC的味道,真香。 #include<cstdio> #include<iostream> #include<algorithm> #include<string> #include<cstring> #include<queue> #inc...

一只不争气的蒸汽机的博客 413

STM32智能小车控制舵机转向

文章目录前言一、舵机简单介绍及接线方式二、cubeMX配置三、代码解析总结 前言 本文将带大家学习如何驱动舵机转向 一、舵机简单介绍及接线方式 信号线(黄线)红线(电源线)棕色(地线) 舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的: 0.5ms--------------0度; 1.0ms------------45度; 1.5ms------------90度; 2

m0_49476241的博客 8614

工业缺陷标注要人命?我从零搭了一套自动标注系统,标注效率直接提升10倍

你是不是也深陷工业缺陷标注的无尽内耗?这不是个例,工业视觉项目落地,80%的时间和成本,都耗在了数据标注环节。普通的图像标注(猫狗分类、人脸识别),标注门槛低、规则简单、一致性要求宽松;而工业缺陷标注,是CV领域公认的地狱级难度:缺陷尺寸小到几像素、种类繁杂且非标、行业专业性极强、标注精度要求到像素级、正负样本极度不均衡,人工标注不仅效率低、成本高,更直接决定了模型的最终上限。我在工业视觉行业摸爬滚打了6年,踩遍了人工标注的所有坑,最终从零搭建了一套工业缺陷专用的闭环自动标注系统,把原来一张图30分钟的标注

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 203

【POJ 3580】 SuperMemo

【题目链接】           点击打开链接【算法】          本题也是Splay区间操作的模板题,不过要比BZOJ 3223要稍微复杂一些,做完此题后,我终于对Splay有了更深入的理解,有“拨开云雾见青天”的感觉            本题还是有许多细节的,笔者花了5h才通过了此题【代码】          #include &lt;algorithm&gt; #include &l...

even_bao的博客 563

浅聊开关电源6:大学生电赛(电源类)之LCL并网滤波器设计(PCB设计,STM32F4xx程序与Simulink仿真)

关于LCL并网滤波器设计的一些小分享

xjtuymh的博客 3655

poj3580 SuperMemo splay --- 从入门到入土

(太可怕了,我只是一个刚学懂splay的蒟蒻) poj地址:http://poj.org/problem?id=3580 AcWing地址:https://www.acwing.com/problem/content/268/ 题意: 给你一个数列 A1~An 有几个操作: 输入格式 第一行包含一个整数 n。 接下来 n 行给出了序列中的数。 接下来一行包含一个整数 ...

forOnward的博客 471

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

poj 3580 SuperMemo(Splay)

基本包括了Splay Tree的所有操作,插入,删除,右移,翻转,区间更新,区间查询。学习Splay Tree推荐一个博客,FZU_Jason。这道题基本上就是抄的他的。。 #include #include #include #include #include #define LL long long #define CLR(a, b) memset(a, b, memset(a)) usin

ok_again的专栏 1166

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

[POJ3580]SuperMemo(无旋Treap)

SuperMemo Time Limit: 5000MSMemory Limit: 65536KTotal Submissions: 17538Accepted: 5496Case Time Limit: 2000MSDescriptionYour friend, Jackson is invited to a TV show called SuperMemo in which the part...

Ephemeral 628

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【序列之神splay】poj3580

首先借助Google大叔吧这道题看懂了。和【noi维护数列】比较相像,可以说是其简化版本,需要维护的东西少一点,操作要多一个。简要的来说,他是要支持者样几种操作:     1.插入删除;     2.翻转一段选定的序列;     3.交换两段相邻的序列;     4.一段全部增加k;     5.询问一段的最小值。前一段时间学习了一下Splay,亮点就在与Splay操作,由此便可以对区间进行划分,比如对于以上操作(首先插入个极大点和极小点):     1.插入 j 到 i 后面:             

Evil.livE 3242

POJ 3580 (可持久化Treap)

#include&amp;lt;iostream&amp;gt; #include&amp;lt;stdio.h&amp;gt; #include&amp;lt;algorithm&amp;gt; using namespace std; struct node{ node *l,*r; int v,w,delta,size,rev,minx; void up(){ minx=v; s...

兜率工的博客 373

poj 3580 SuperMemo

伸展树

GadyPu的专栏 352

Poj3580 Super Memo(FHQ-Treap)

题面 题解 对于操作$1$,我们可以对于每个节点打一个$add$标记,下放就行了 对于操作2,可以参考这篇题解的上一篇,不赘述 对于操作4,可以将区间裂成两部分,然后再插入合并 对于操作5,可以将区间裂成三部分,删除其中一个部分,合并其他两部分 对于操作6,打一个$min$标记,具体可以看代码。 对于操作3,这个有点复杂,但是手玩可以发现,修改完后只是某两个断开的区间换了位置,只...

weixin_30725315的博客 215

poj 3580

平衡树裸题,这是新的平衡树模板。 平衡树,区间加值,区间翻转,区间查询最小值。 我还是太年轻了。。。too young too simple。。。

Dash 744

[poj3580]SuperMemo(splay终结题)

传送门 题意: 你需要维护一组数字,包括这样的几个操作: 给出一个数字序列,有6种操作: 1、 ADD l r d:区间[l,r]的数都加上d。 2、 REVERSE l r : 将区间[l,r]中的数翻转 。 3、 REVOLVE l r t :将区间[l,r]旋转t次,如1 2 3 4 5 旋转2次后就变成4 5 1 2 3 。 4、 INSERT p x :在第p个数后面插入x 。 5、D...

私は Mocha!! 693

告别调试烦恼:ST-Link在Keil中的高级调试技巧与内存/外设查看实战

本文详细介绍了ST-Link在Keil中的高级调试技巧,包括内存/外设查看实战,帮助开发者提升调试效率。通过Watch窗口、Memory窗口和System Viewer等工具,实现寄存器级外设状态可视化和变量动态监控,解决常见调试问题。特别适合需要高效排查硬件异常的嵌入式开发者。

weixin_30530939的博客 595

POJ3580 SuperMemo

splay模板

Monster__Yi的博客 1115

java的流间隔问题_java – SuperMemo(SM-2)的间隔重复算法

SuperMemo算法>重复 – 这是用户看到闪卡的次数. 0表示他们尚未研究过,1表示这是他们的第一次,依此类推.在一些文档中它也被称为n.>质量 – 也称为评估质量.这是闪存卡的难度(由用户定义).比例从0到5.> easyiness – 这也称为easyiness factor或EFactor或EF.它是乘数,用于增加间隔重复的“空间”.范围从1.3到2.5.> i...

weixin_39621669的博客 996

POJ 3580

题意:给一个数组,有6种操作: add  x y d : [x,y]中所有数加d reverse x y: [x,y]区间翻转 revolve x y t: [x,y]循环右移t位,t可取任意整数 insert  x v: 在第x个位置插入一个值为v的数 delete x : 删除第x个数 min x y : 求区间[x,y]的最小值 题解:典型splay,通过旋转

tmeteorj的专栏 1697
上一篇: 蓝书(算法竞赛进阶指南)刷题记录——BZOJ3674可持久化并查集加强版题解(启发式合并+并查集+主席树)
下一篇: 蓝书(算法竞赛进阶指南)刷题记录——hdu4348 To the moon(主席树)
hezlik
博客等级 码龄9年 111粉丝 241原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值