/******************************************
数据结构:
Splay_Tree,伸展树;
性质:
伸展树是二叉查找树的一种改进;
与二叉查找树一样,伸展树也具有有序性;
即伸展树中的每一个节点x都满足:
该节点左子树中的每一个元素都小于x;
而其右子树中的每一个元素都大于x;
与普通二叉查找树不同的是,伸展树可以自我调整;
特点:
伸展树并不是严格意义上的平衡树;
也还是极有可能退化成线性结构,但伸展操作能使它的每一次操作近似(logn);
伸展操作:
伸展操作和平衡树的保持平衡是类似的;
只不过他不要求保持平衡,只是相应的旋转;
旋转有三种情况要处理:
(1)Zig或Zag(节点x的父节点y是根节点)
(2)Zig-Zig或Zag-Zag(节点x的父节点y不是根节点,且x与y同时是各自父节点的左孩子或者同时是各自父节点的右孩子)
(3)Zig-Zag或Zag-Zig(节点x的父节点y不是根节点,x与y中一个是其父节点的左孩子而另一个是其父节点的右孩子)
即一字型旋转和之字型旋转;
优势:
能快速定位一个区间[l,r],并且能将区间进行删除、旋转操作;
将第l-1个结点旋转至根(之前的Splay操作),将第r+1个结点旋转至根的右孩子;
由于伸展树的本质还是二叉搜索树,则根据二叉查找树的性质可以知道;
在这两个结点之间,也是根的右孩子的左子树就包括节点[l,r];
即很快定位了区间[l,r],如果需要删除,直接把子树拿走即可;
算法测试:
PKU3468(A Simple Problem with Integers)
题目大意:
Q a b   :查询区间[a,b]的和;
C a b x : 更新区间[a,b],区间所有值加上x;
*******************************************/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define Key_value ch[ch[root][1]][0]//进行各种操作的区间
const int INF=0xffffff;
const int N=100010;
typedef long long LL;
int ch[N][2];//左右孩子(0为左孩子,1为右孩子)
int pre[N];//父结点
int key[N];//数据域
int size[N];//树的规模
int val[N];
int add[N];
int a[N];//结点元素
LL sum[N];//子树结点和
int root;  //根结点
int tot;//结点数量
int n,q;
void Push_Up(int u)//通过孩子结点更新父结点
{
size[u]=size[ch[u][0]]+size[ch[u][1]]+1;
sum[u]=sum[ch[u][0]]+sum[ch[u][1]]+val[u]+add[u];
}
void Push_Down(int u)//将延迟标记更新到孩子结点
{
if(add[u])
{
val[u]+=add[u];
add[ch[u][0]]+=add[u];
add[ch[u][1]]+=add[u];
sum[ch[u][0]]+=(LL)add[u]*size[ch[u][0]];
sum[ch[u][1]]+=(LL)add[u]*size[ch[u][1]];
add[u]=0;
}
}
void New_Node(int &u,int f,int c)//新建一个结点,f为父节点
{
u=++tot;
val[u]=sum[u]=c;
pre[u]=f;
size[u]=1;
ch[u][1]=ch[u][0]=add[u]=0;
}
void Build_Tree(int &u,int l,int r,int f)//建树,中间结点先建立,然后分别对区间两端在左右子树建立
{
if(l>r)
return;
int m=(l+r)>>1;
New_Node(u,f,a[m]);
if(l<m)
Build_Tree(ch[u][0],l,m-1,u);
if(r>m)
Build_Tree(ch[u][1],m+1,r,u);
Push_Up(u);
}
void Rotate(int x,int c)//旋转操作,c=0 表示左旋,c=1 表示右旋
{
int y=pre[x];
Push_Down(y);// 先将Y结点的标记向下传递(因为Y在上面)
Push_Down(x);//再把X的标记向下传递
ch[y][!c]=ch[x][c];//类似SBT,要把其中一个分支先给父节点
pre[ch[x][c]]=y;
pre[x]=pre[y];
if(pre[y])//如果父节点不是根结点,则要和父节点的父节点连接起来
{
ch[pre[x]][ch[pre[y]][1]==y]=x;
}
pre[y]=x;
ch[x][c]=y;
Push_Up(y);
}
void Splay(int x,int f)//Splay操作,把根结点x转到结点f的下面
{
Push_Down(x);
while(pre[x]!=f)
{
int y=pre[x];
if(pre[y]==f)//父结点的父亲即为f,执行单旋转
Rotate(x,ch[y][0]==x);
else
{
int z=pre[y];
int g=(ch[z][0]==y);
if(ch[y][g]==x)
Rotate(x,!g),Rotate(x,g);//之字形旋转
else Rotate(y,g),Rotate(x,g);//一字形旋转
}
}
Push_Up(x);// 最后再维护X结点
if(f==0)//更新根结点
{
root=x;
}
}
void Rotate_Under(int k,int f)//把第k位的数伸展到f下方
{
//找到处在中序遍历第k个结点,并将其旋转到结点f 的下面
int p=root;//从根结点开始
Push_Down(p);// 由于要访问p的子结点,将标记下传
while(size[ch[p][0]]!=k)//p的左子树的大小
{
if(k<size[ch[p][0]])// 第k个结点在p左边,向左走
{
p=ch[p][0];
}
else//否则在右边,而且在右子树中,这个结点不再是第k个
{
k-=(size[ch[p][0]]+1);
p=ch[p][1];
}
Push_Down(p);
}
Splay(p,f);//执行旋转
}
int Insert(int k)//插入结点
{
int r=root;
while(ch[r][key[r]<k])
r=ch[r][key[r]<k];
New_Node(ch[r][k>key[r]],r,k);
//将新插入的结点更新至根结点
//Push_Up(r);
Splay(ch[r][k>key[r]],0);
return 1;
}
int Get_Pre(int x)//找前驱,即左子树的最右结点
{
int tmp=ch[x][0];
if(tmp==0)
return INF;
while(ch[tmp][1])
{
tmp=ch[tmp][1];
}
return key[x]-key[tmp];
}
int Get_Next(int x)//找后继,即右子树的最左结点
{
int tmp=ch[x][1];
if(tmp==0)
return INF;
while(ch[tmp][0])
{
tmp=ch[tmp][0];
}
return key[tmp]-key[x];
}
LL Query(int l,int r)//查询[l,r]之间的和
{
Rotate_Under(l-1,0);
Rotate_Under(r+1,root);
return sum[Key_value];
}
void Update(int l,int r)//更新
{
int k;
scanf("%d",&k);
Rotate_Under(l-1,0);
Rotate_Under(r+1,root);
add[Key_value]+=k;
sum[Key_value]+=size[Key_value]*k;
}
void Init()//初始化
{
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
ch[0][0]=ch[0][1]=pre[0]=size[0]=0;
add[0]=sum[0]=0;
root=tot=0;
New_Node(root,0,-1);
New_Node(ch[root][1],root,-1);   //头尾各加入一个空位
size[root]=2;
Build_Tree(Key_value,0,n-1,ch[root][1]);  //让所有数据夹在两个-1之间
Push_Up(ch[root][1]);
Push_Up(root);
}
int main()
{
while(~scanf("%d%d",&n,&q))
{
Init();
while(q--)
{
char op;
scanf(" %c",&op);
int x,y;
scanf("%d%d",&x,&y);
if(op=='Q')
printf("%lld\n",Query(x,y));
else
Update(x,y);
}
}
return 0;
}

Spaly_Tree 模版相关推荐

  1. HDU 3549 Flow Problem(最大流模版EK算法)

    题目链接 第一道最大流,赤裸裸的模版题,刚好可以熟悉模版用.今天看了一下最大流,就看了一个EK算法,感觉有点和二分图匹配算法有点相似,对于最大流问题有点了解了,不过为什么这么做,也不是 很懂,只是把代 ...

  2. smarty mysql demo_PHP Smarty模版简单使用方法

    本文实例讲述了PHP Smarty模版简单使用方法.分享给大家供大家参考,具体如下: Index.php: require('../libs/Smarty.class.php'); $smarty = ...

  3. C++ 通过模版工厂实现 简单反射机制

    前言 我们知道Java/Python这种语言能够很好得 支持反射.反射机制 就是一种用户输入的字符串到对应实现方法的映射,比如http接口中 用户传入了url,我们需要调用该url对应的方法/函数对象 ...

  4. C++ 泛型编程 -- 函数模版

    文章目录 定义 声明 调用方式 函数模版的重载 函数模版的特点 工作中一个同事写了测试demo,想要自己尝试使用发现调用老出错,请教的时候发现是函数模版,有自己的调用方式,并且发现核心代码中大量的函数 ...

  5. Fastadmin管理Mysql_FastAdmin-CMS模版制作(6)-正式部署

    一.工具信息介绍 (1)服务器系统:CentOS7.2 64位系统: (2)服务器面板:宝塔,官网地址:https://www.bt.cn/: (3)PHP7.2: (4)mysql5.6: (5)N ...

  6. 知方可补不足~开发人员可以自己定义VS文件模版

    团队开发,最重要的是什么? 统一的规范,对于一个团队,在开发项目之前,必须要先告诉大家项目的规范是什么,而开发人员在实际当中再去执行这个规范,对于规范事实上是个很宏观的概念,它可能有很多版本,呵呵,如 ...

  7. 动软代码生成V2.74模版简介

    最近发现很多人用动软代码生成,确实方便,有些经验记录下,以后查看回顾. ..\Maticsoft\Codematic2\Template\TemplateFile 为模板文件夹,直接在目录下新建文件夹 ...

  8. java类的注释模板_IDEA添加Java类注释模版的方法

    本文介绍了idea添加java类注释模版的方法,分享给大家,具体如下: idea版本:intellij idea 2017.2.5 x64 eclipse能在类上方输入/**,回车添加类注释模版,但i ...

  9. 发微信模版消息换行用\n

    发微信模版消息换行用\n 发微信模版消息换行用\n 发微信模版消息换行用\n 发微信模版消息换行用\n 发微信模版消息换行用\n 转载于:https://blog.51cto.com/xuqin/19 ...

最新文章

  1. 编程模拟洗牌和发牌过程c语言,洗牌发牌模拟系统课程设计报告.doc
  2. android 无埋点 简书,无埋点README
  3. cglib与java反射的比较
  4. 【高德地图开发1】---简介
  5. 大工17春计算机应用基础在线测试2答案,大工14春《计算机应用基础》在线测试2...
  6. nginx生成ssl证书
  7. 《看完它面试必solo | 寻找C站宝藏》
  8. Ninject使用demo
  9. Spring boot(九):定时任务
  10. NodeJS 模板 -- jade
  11. python读取linux内存_使用python获取CPU和内存信息(linux系统)
  12. 廖雪峰python教程-福利 | 廖雪峰官方Python教程,拿走不谢!
  13. 搭建公司内部的NuGet服务器
  14. 区块链开发之Solidity编程基础(一)
  15. 人工智能智能制作PPT构想---论文与PPT介绍
  16. AnkhSvn推出1.02支持vs2008
  17. web前端工程师工资待遇 各阶段所需要的技术
  18. 利用5次shift漏洞破解win7密码
  19. 苹果超薄笔记本MBA设计缺陷
  20. 芯片、二代测序的差别及GEO数据库界面

热门文章

  1. 角色关联权限操作-代码实现
  2. 微服务调用组件Feign:简介以及搭建环境
  3. 从一个极简的微服务架构开始
  4. SpringBoot 配置错误页
  5. mac os mysql 命令_Mac环境下MySQL的安装和基本命令的使用
  6. 计算机博士专业学位,河海大学计算机应用技术博士专业学位研究生培养方案
  7. Java 语法规定之外的命名注释规范
  8. 【图文详解】Mysql8.0安装教程
  9. 前端必知必会--JSON.stringify()犀利的第三个参数
  10. Spring+Quartz实现定时任务