ODT(old driver tree)详解(带例题)
ODT简介
ODT(old driver tree 老驱动树)又名珂朵莉树是由codeforcescodeforcescodeforces上一位叫做ODTODTODT的用户提出的一种基于平衡树的暴力数据结构。
这个数据结构的玄妙之处在于它并没有稳定的时间复杂度,因此只有在数据随机/水的情况下才会有较好的表现。
实现前提&&实现原理
前提是必须要有区间覆盖操作且数据较随机/水
实现原理:将元素相同的区间推平一起处理,即如果区间[l,r][l,r][l,r]中的所有数[al,al+1...ar][a_l,a_{l+1}...a_r][al,al+1...ar]全部相同的话就将这个区间的信息用一个节点表示。
从上述描述可以看出这个数据结构是非常暴力玄学的
初始化
然后对于每段区间我们可以用一个三元组[l,r,v][l,r,v][l,r,v]来表示它的左/右端点和整个区间的值,然后对于这些区间的信息可以用一个setsetset来维护。
下面是ODTODTODT节点的初始化代码:
struct Node{
int l,r;
mutable int v;
Node(int l,int r=-1,int v=0):l(l),r(r),v(v){}
friend inline bool operator<(const Node&a,const Node&b){
return a.l<b.l;
}
};
set<Node>S;
typedef set<Node>::iterator It;
然后我们要谈谈ODTODTODT两个重要的操作splitsplitsplit和assignassignassign
split操作
ODTODTODT的splitsplitsplit函数split(pos)split(pos)split(pos)表示把pospospos所在的这个区间[l,r,v][l,r,v][l,r,v]分成[l,pos−1,v][l,pos-1,v][l,pos−1,v]和[pos,r,v][pos,r,v][pos,r,v]并且返回后者的迭代器。
实现很简单直接lowerboundlower_boundlowerbound出pospospos所在的区间然后加几个小特判。
代码:
inline It split(int pos){
It it=S.lower_bound(pos);
if(it!=S.end()&&it->l==pos)return it;
--it;
if(pos>it->r)return S.end();
int l=it->l,r=it->r,v=it->v;
S.erase(it);
S.insert(Node(l,pos-1,v));
return S.insert(Node(pos,r,v)).first;
}
assign操作
ODTODTODT最核心的操作assignassignassign,assign(l,r,v)assign(l,r,v)assign(l,r,v)表示把区间[l,r][l,r][l,r]全部赋值为vvv并且会将这r−l+1r-l+1r−l+1个点合并成一个ODTODTODT节点插入到ODTODTODT中,由于数据随机的时候ODTODTODT中节点会快速减少,因此ODTODTODT复杂度此时十分接近O(nlogn)O(nlog_n)O(nlogn)
具体实现可以通过上面提到的splitsplitsplit函数。
代码:
inline void assign(int l,int r,int v){
It R=split(r+1),L=split(l);
S.erase(L,R),S.insert(Node(l,r,v));
}
其它操作
至此,与ODTODTODT相关的操作已经基本讲完了。
剩下的操作与ODTODTODT本身关系并不大,相当于就是遍历每一个ODTODTODT节点暴力进行修改和查询。
区间第k小
代码:
typedef set<Node>iterator It;
typedef pair<long long,int> pli;
vector<pli>q;
inline int rank(int l,int r,int kth){
It R=split(r+1),L=split(l);
q.clear();
for(It it=L;it!=R;++it)q.push_back(pli(it->v,it->r-it->l+1));
sort(q.begin(),q.end());
for(ri i=0;i<q.size();++i){
kth-=q[i].second;
if(kth<=0)return q[i].first;
}
return -1;
}
区间加
代码:
inline void add(int l,int r,int v){
It L=split(l),R=split(r+1);
for(It it=L;it!=R;++it)(it->v)+=v;
}
区间所有数的k次方和
代码:
typedef long long ll;
inline ll query(int l,int r,int k,ll mod){
ll ret=0;
It L=split(l),R=split(r+1);
for(It it=L;it!=R;++it)ret=(ret+(ll)(it->r-it->l+1)*ksm(it->v,k,mod)%mod)%mod;
return ret;
}
几道水题
codeforces896Ccodeforces896Ccodeforces896C
codeforces915Ecodeforces915Ecodeforces915E
codeforces343Dcodeforces343Dcodeforces343D
bzoj4592bzoj4592bzoj4592
洛谷2787洛谷2787洛谷2787
ODT(old driver tree)详解(带例题)的更多相关文章
- Apache的配置详解 带图
对Apache 的 Http.conf 各项配置详解 1.01 ServerRoot 配置 [ServerRoot "" 主要用于指定 Apache 的安装路径,此选项参数值在安装 ...
- [转] 关于Struts-JSON配置(详解带实例struts2的json数据支持)
关于Struts-JSON的提高开发效率 一.JSON是什么? :JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写,同时也易于机器解 析和 ...
- 【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解
本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情 ...
- dsu on tree详解
这个算法还是挺人性化的,没有什么难度 就是可能看起来有点晕什么的. 大体 思想是 利用重链刨分来优化子树内部的查询. 考虑一个问题要对每个子树都要询问一次.我们暴力显然是\(n^2\)的. 考虑一下优 ...
- c#操作MangoDB 之MangoDB CSharp Driver驱动详解
序言 MangoDB CSharp Driver是c#操作mongodb的官方驱动. 官方Api文档:http://api.mongodb.org/csharp/2.2/html/R_Project_ ...
- BIT 树状数组 详解 及 例题
(一)树状数组的概念 如果给定一个数组,要你求里面所有数的和,一般都会想到累加.但是当那个数组很大的时候,累加就显得太耗时了,时间复杂度为O(n),并且采用累加的方法还有一个局限,那就是,当修改掉数组 ...
- 二叉查找树(binary search tree)详解
二叉查找树(Binary Search Tree),也称二叉排序树(binary sorted tree),是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于 ...
- C#调用存储过程详解(带返回值、参数输入输出等)
CREATE PROCEDURE [dbo].[GetNameById] @studentid varchar(8), @studentname nvarchar(50) OUTPUT AS BEGI ...
- BTree和B+Tree详解
https://www.cnblogs.com/vianzhang/p/7922426.html B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引.B+树中的B代表平 ...
随机推荐
- Android使用VideoView播放本地视频及网络视频Demo
1.xm文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and ...
- JS获取鼠标左(右)滑事件
鼠标左(右)滑也是网站开发中常见的效果之一,这里对鼠标左(右)滑做出一些解释. 首先要获取需要左右滑事件的节点: eg: var div=document.getElementById("d ...
- nth-child & nth-of-type区别
Do l have to 非做不可吗? He is my age. 他和我同岁. Here you are. 给你. No one knows . 没有人知道. 关于nth-child &&a ...
- PHP面向对象之类的自动加载
类的自动加载 含义: 当某行代码需要一个类的时候,php的内部机制可以做到“自动加载该类文件”,以满足该行需要一个类的这种需求. 什么时候需要一个类? 1,new一个对象的时候: 2,使用一个类的静态 ...
- WAV与PCM
转: 1.PCM格式介绍: PCM(Pulse Code Modulation)也被称为 脉码编码调制.PCM中的声音数据没有被压缩,如果是单声道的文件,采样数据按时间的先后顺序依次存入.(它的基本组 ...
- Requested a new session but one was in progress
作为appium初学者,估计很多人都会遇到这个错误.如何解决: 1.环境变量中去掉appium的安装路径,添加Appium\node_modules\.bin这个路径进去. 2.启动cmd 输入app ...
- iOS 集成极光推送
最近极光推送更新到V3版本之后,推送又不成功!配合服务器联调了半天,发现是服务器环境配置有问题. 想着就把极光推送的步骤给记录下来. 一.配置push证书 这个可以到极光文档里写,很详细 二.导入必要 ...
- (八) .launch文件 ---编写简单的启动脚本文件
下面我们将介绍,如何编写一个启动脚本程序:(.launch文件) 还记得我们在 创建ROS软件包教程 中创建的第一个程序包(beginner_tutorials)吗,现在我们要使用它. 在 begin ...
- 【MINA学习笔记】—— 1.体系结构分析[z]
前言 Apache的MINA框架是一个早年非常流行的NIO框架,它出自于Netty之父Trustin Lee大神之手.虽然目前市场份额已经逐渐被Netty取代了,但是其作为NIO初学者入门学习框架是非 ...
- HTTP Basic Authentication认证(Web API)
当下最流行的Web Api 接口认证方式 HTTP Basic Authentication: http://smalltalllong.iteye.com/blog/912046 什么是HTTP B ...