珂朵莉树(Chtholly Tree)学习笔记
珂朵莉树(Chtholly Tree)学习笔记
珂朵莉树原理
其原理在于运用一颗树(set,treap,splay......)其中要求所有元素有序,并且支持基本的操作(删除,添加,查找......)来实现区间压缩。
那么区间压缩的意义在于区间推平这是珂朵莉树的核心(如果没有这个操作实际上不一定需要这种算法)
ps:若保证有连续相等甚至递增的区间,也可以的(吧?)。
可想而知它的操作在于对区间的分裂和合并操作
(为什么?因为这样可以方便而快捷的区间推平)
珂朵莉树的实现
在众多树中因为set这个c++自带,所以决定选择它。
结构
一个node结构体——把它叫区间(已typedef long long LL)
struct node
{
int l,r;LL v;//这里官方写法加了一个mutable,看个人写法
node(int L,int R,LL V):l(L),r(R),v(V){}
bool operator < (const node& o) const
{
return l<o.l;
}
};
声明集合
set<node>s;
初始化
for(int i=1;i<=n;++i)
s.insert(i,i,val);
s.insert(n+1,n+1,0);//见下面中it!=s.end()的前提
分裂
#define it_ set<node>::iterator
it_ split(int pos)
{
it_ it=s.lower_bound(node(pos));
if(it!=s.end()&& it->l==pos) return it;
--it;
int ll=it->l,rr=it->r;
LL vv=it->v;
s.erase(it);
s.insert(node(ll,pos-1,vv));
return s.insert(node(pos,rr,vv)).first;
}
区间推平
void assign(int l,int r,LL val=0)
{
it_ itl=split(l),itr=split(r+1);
s.erase(itl,itr);
s.insert(node(l,r,val));
}
如上。
栗例子
见cf896c
仅仅给出代码
#include <bits/stdc++.h>
#define it_ set<node>::iterator
// #define swap(X,Y) {int (tmp)=(X),(X)=(Y),(Y)=(tmp);}
using namespace std;
typedef long long LL;
const int M7=1e9+7;
const int maxn=1e5+5;
int n,m;
LL seed,vmax;
LL a[maxn];
struct node
{
int l,r;mutable LL v;
node(int L,int R=-1,LL V=0):l(L),r(R),v(V){}
bool operator < (const node& o) const
{
return l<o.l;
}
};
set<node>s;
it_ split(int pos)
{
it_ it=s.lower_bound(node(pos));
if(it!=s.end()&& it->l==pos) return it;
--it;
int ll=it->l,rr=it->r;
LL vv=it->v;
s.erase(it);
s.insert(node(ll,pos-1,vv));
return s.insert(node(pos,rr,vv)).first;
}
void assign(int l,int r,LL val=0)
{
it_ itl=split(l),itr=split(r+1);
s.erase(itl,itr);
s.insert(node(l,r,val));
}
void add(int l,int r,LL val=0)
{
it_ itl=split(l),itr=split(r+1);
for(it_ i=itl;i!=itr;++i)
{
i->v+=val;
}
}
LL so(int l,int r,int k)
{
it_ itl=split(l),itr=split(r+1);
vector<pair<LL,int>>v;
v.clear();
for(;itl!=itr;++itl)
{
v.push_back(pair<LL,int>(itl->v,itl->r-itl->l+1));
}
sort(v.begin(),v.end());
for(vector<pair<LL,int>>::iterator it=v.begin();it!=v.end();++it)
{
k-=it->second;
if(k<=0)return it->first;
}
}
LL pow(LL a,LL b,LL mod)
{
LL ret=1;a%=mod;
while(b)
{
if(b&1) ret=ret*a%mod;
a=a*a%mod;
b>>=1;
}
return ret%mod;
}
LL ok(int l,int r,LL k,LL mod)
{
it_ itl=split(l),itr=split(r+1);
LL ans=0;
for(;itl!=itr;++itl)
{
ans+=(LL)(itl->r-itl->l+1)*pow(itl->v,k,mod)%mod;
ans%=mod;
}
return ans%mod;
}
LL rnd()
{
LL ret=seed;
seed=(seed*7+13)%M7;
return ret;
}
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(0);
cin>>n>>m>>seed>>vmax;
for(int i=1;i<=n;++i)
{
a[i]=(rnd()%vmax)+1;
s.insert(node(i,i,a[i]));
}
s.insert(node(n+1,n+1,0));
for(int i=1;i<=m;++i)
{
int op=(rnd()%4)+1,
l=(rnd()%n)+1,
r=(rnd()%n)+1;LL x,y;
if(l>r)
swap(l,r);
if(op==3)
x=(rnd()%(LL)(r-l+1))+1;
else
x=(rnd()%vmax)+1;
if(op==4)
y=(rnd()%vmax)+1;
if(op==1) add(l,r,x);
else if(op==2) assign(l,r,x);
else if(op==3) cout<<so(l,r,x)<<endl;
else if(op==4) cout<<ok(l,r,x,y)<<endl;
}
return 0;
}
珂朵莉树(Chtholly Tree)学习笔记的更多相关文章
- 「学习笔记」珂朵莉树 ODT
珂朵莉树,也叫ODT(Old Driver Tree 老司机树) 从前有一天,珂朵莉出现了... 然后有一天,珂朵莉树出现了... 看看图片的地址 Codeforces可还行) 没错,珂朵莉树来自Co ...
- 『珂朵莉树 Old Driver Tree』
珂朵莉树 珂朵莉树其实不是树,只是一个借助平衡树实现的数据结构,主要是对于有区间赋值的数据结构题,可以用很暴力的代码很高效地完成任务,当然这是建立在数据随机的基础上的. 即使数据不是随机的,写一个珂朵 ...
- 珂朵莉树(ODT)笔记
珂朵莉树,又叫老司机树($Old\, Driver \, Tree$) 是一种暴力出奇迹,就怕数据不随机的数据结构. 适用 需要用线段树维护一些区间修改的信息…… 像是区间赋值(主要),区间加…… 原 ...
- CF896C Willem, Chtholly and Seniorious(珂朵莉树)
中文题面 珂朵莉树的板子……这篇文章很不错 据说还有奈芙莲树和瑟尼欧里斯树…… 等联赛考完去学一下(逃 //minamoto #include<bits/stdc++.h> #define ...
- [转]我的数据结构不可能这么可爱!——珂朵莉树(ODT)详解
参考资料: Chtholly Tree (珂朵莉树) (应某毒瘤要求,删除链接,需要者自行去Bilibili搜索) 毒瘤数据结构之珂朵莉树 在全是珂学家的珂谷,你却不知道珂朵莉树?来跟诗乃一起学习珂朵 ...
- 洛谷$P2572\ [SCOI2010]$ 序列操作 线段树/珂朵莉树
正解:线段树/珂朵莉树 解题报告: 传送门$w$ 本来是想写线段树的,,,然后神仙$tt$跟我港可以用珂朵莉所以决定顺便学下珂朵莉趴$QwQ$ 还是先写线段树做法$QwQ$? 操作一二三四都很$eas ...
- 题解 P3372 【【模板】线段树 1】(珂朵莉树解法)
这道题可以用珂朵莉树做,但是由于数据比较不随机,而我也没有手写一颗平衡树,所以就被卡掉了,只拿了70分. 珂朵莉树是一种基于平衡树的(伪)高效数据结构. 它的核心操作是推平一段区间. 简而言之,就是把 ...
- 洛谷AT2342 Train Service Planning(思维,动态规划,珂朵莉树)
洛谷题目传送门 神仙思维题还是要写点东西才好. 建立数学模型 这种很抽象的东西没有式子描述一下显然是下不了手的. 因为任何位置都以\(k\)为周期,所以我们只用关心一个周期,也就是以下数都在膜\(k\ ...
- 洛谷P4344 [SHOI2015]脑洞治疗仪(珂朵莉树)
传送门 看到区间推倒……推平就想到珂朵莉树 挖脑洞直接assign,填坑先数一遍再assign再暴力填,数数的话暴力数 //minamoto #include<iostream> #inc ...
随机推荐
- ChartCtrl源码剖析之——CChartLegend类
CChartLegend类用来绘制每一个波形的描述信息,它处于该控件的区域,如下图所示: CChartLegend类的头文件. #if !defined(AFX_CHARTLEGEND_H__CD72 ...
- supervisor - Python进程管理工具
经常会碰到要写一些守护进程,简单做法放入后台: shell> nohup python xxx.py & 偶尔这么做还可以接受,如果一堆这样的呢? 当然还有一个问题,就是各种服务,对应的 ...
- 使用VirtualBox虚拟机搭建局域网
参考资料: http://www.awaimai.com/995.html https://my.oschina.net/cofecafe1/blog/206535 最近公司局域网网络改造,在改造前已 ...
- Access operations
Access operations Accessing elements inside tensors Suppose we have the following tensors: > t = ...
- APP支付宝登录第三方授权如何签约入口在哪里
最近,公司项目要接入支付宝授权登录,第三方SDK接入过不少,一顿按照流程操作.到签约的步骤的时候就把我难住了,入口一直找不到.然后在文档中心搜索“支付宝登录签约”,找到一个申请地址.心想终于找到你了, ...
- 基于ssh框架web示例
基于ssh框架web示例 介绍 Spring Boot Web 开发非常简单,该示例包括包括目前web开发基本都需要用到的内容 - 序列化(json)输出 - 过滤器(filters) - 监视器(l ...
- Sign on Fence CodeForces - 484E
http://codeforces.com/problemset/problem/484/E 题意: 给定一个长度为n的数列,有m次询问,询问形如l r k 要你在区间[l,r]内选一个长度为k的区间 ...
- 离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers
题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问.还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前 ...
- home键拦截
代码: public class HomeKeyReceiver extends BroadcastReceiver { private static final String LOG_TAG = & ...
- 奇葩问题: lsattr -d /data 显示:----------I--e- /data/
奇葩问题 lsattr -d /data 显示:----------I--e- /data/ 问题影响: 其他权限中I(大写i) 目录下不能删除文件,不能添加文件 ================== ...