洛谷 P6136 【【模板】普通平衡树(数据加强版)】
爱死替罪羊树了
这种暴力的数据结构爱死了。什么?!你还不知道替罪羊树?那就看看这篇博客这篇博客吧。替罪羊树就是当不平衡时,拍扁重建,然后就平衡了。想切这道题,要先把普通平衡树那道题做了(这篇博客讲了的哦),然后就会发现,只要改一下以前的程序就可以了。这里我就着重讲下主函数怎么建树那里。
建树方法:
- 一开始我写的方法(指读入建树的时候),长一些,详细的都在代码里面了:
#include <bits/stdc++.h>
using namespace std;
int read(){
int ans = 0;
char ch = getchar();
while(ch > '9' || ch < '0') ch = getchar();
while(ch <= '9' && ch >= '0'){
ans = ans * 10 + ch - '0';
ch = getchar();
}
return ans;
}
struct node{
int ls , rs , f , tsize , fsize , date;
};
node a[2000010];
int memo[2000010] , c[2000010] , ha[2000010];
double alpha = 0.75;
int n , m , root , pool , poi , last , ans;
bool cheak(int now){
if((double)a[now].fsize * alpha >= (double)max(a[a[now].ls].fsize , a[a[now].rs].fsize)) return true;
return false;
}
void dfs(int now){
if(!now) return;
dfs(a[now].ls);
if(a[now].f) c[++poi] = now;
else memo[++pool] = now;
dfs(a[now].rs);
}
void build(int l , int r , int &now){
int mid = (l + r) / 2;
now = c[mid];
if(l == r){
a[now].ls = a[now].rs = 0;
a[now].fsize = a[now].tsize = 1;
return;
}
if(l < mid) build(l , mid - 1 , a[now].ls);
else a[now].ls = 0;
build(mid + 1 , r , a[now].rs);
a[now].fsize = a[a[now].ls].fsize + a[a[now].rs].fsize + 1;
a[now].tsize = a[a[now].ls].tsize + a[a[now].rs].tsize + 1;
}
void rebuild(int &now){
poi = 0;
dfs(now);
if(poi) build(1 , poi , now);
else now = 0;
}
void insert(int &now , int t){
if(!now){
now = memo[pool--];
a[now].date = t;
a[now].fsize = a[now].tsize = a[now].f = 1;
a[now].ls = a[now].rs = 0;
return;
}
a[now].fsize++ , a[now].tsize++;
if(a[now].date >= t) insert(a[now].ls , t);
else insert(a[now].rs , t);
if(!cheak(now)) rebuild(now);
}
int ft(int rk){
int now = root;
while(now){
if(a[now].f && a[a[now].ls].fsize + 1 == rk) return a[now].date;
if(a[a[now].ls].fsize + a[now].f >= rk) now = a[now].ls;
else{
rk -= a[a[now].ls].fsize + a[now].f;
now = a[now].rs;
}
}
}
int frk(int t){
int now = root , ans = 1;
while(now){
if(a[now].date >= t) now = a[now].ls;
else{
ans += a[a[now].ls].fsize + a[now].f;
now = a[now].rs;
}
}
return ans;
}
void delet(int &now , int rk){
if(a[now].f && a[a[now].ls].fsize + 1 == rk){
a[now].f = 0;
a[now].fsize--;
return;
}
a[now].fsize--;
if(a[now].f + a[a[now].ls].fsize >= rk) delet(a[now].ls , rk);
else delet(a[now].rs , rk - a[now].f - a[a[now].ls].fsize);
}
void rdelet(int t){
delet(root , frk(t));
if(a[root].tsize * alpha >= a[root].fsize) rebuild(root);
}
int main(){
n = read() , m = read();
for(int i = 1; i <= n; i++) ha[i] = read();
sort(ha + 1 , ha + n + 1); //手动中序遍历
for(int i = 2000000; i >= 1; i--) memo[i] = ++pool;
for(int i = 1; i <= n; i++){
c[i] = i; //模拟dfs操作
a[i].date = ha[i]; //把值放回去
a[i].f = 1; //这个点存在
}
pool -= n; //用了n个内存,内存池里面取n出来
build(1 , n , root); //建树
while(m--){
int opt , x , y;
opt = read() , x = read();
x = last ^ x;
if(opt == 1) insert(root , x);
if(opt == 2) rdelet(x);
if(opt == 3) y = frk(x) , ans = ans ^ y , last = y;
if(opt == 4) y = ft(x) , ans = ans ^ y , last = y;
if(opt == 5) y = ft(frk(x) - 1) , ans = ans ^ y , last = y;
if(opt == 6) y = ft(frk(x + 1)) , ans = ans ^ y , last = y;
}
cout << ans;
return 0;
}
- 同学写的,短了很多啊,但是似乎我要快一点,我也不知道为什么,可能是因为直接insert的话,数据专门把树卡成链后,重建次数太多,导致要慢一点,而我直接sort快一些(大雾):
for(register int i = 1; i <= n; i++){
x = read();
insert(root , x);
}
吐槽:这道题数据还是有点水吧,比较未加强数据的直接搬过来能AC,可能是为了卡朝鲜树之类的数据结构吧。
洛谷 P6136 【【模板】普通平衡树(数据加强版)】的更多相关文章
- 洛谷 P1120 小木棍 [数据加强版]解题报告
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 洛谷——P1120 小木棍 [数据加强版]
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍 ...
- 洛谷 P1120 小木棍 [数据加强版]
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 洛谷 P2241统计方形(数据加强版) 题解
题目传送门 说是加强版,其实可以把棋盘那道题的代码粘过来(注意要开long long): #include<bits/stdc++.h> using namespace std; ,c; ...
- 洛谷—— P1120 小木棍 [数据加强版]
https://www.luogu.org/problem/show?pid=1120 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接 ...
- 洛谷——P2241 统计方形(数据加强版)
https://www.luogu.org/problem/show?pid=2241 题目背景 1997年普及组第一题 题目描述 有一个n*m方格的棋盘,求其方格包含多少正方形.长方形 输入输出格式 ...
- 洛谷.3369.[模板]普通平衡树(Splay)
题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...
- 洛谷.3369.[模板]普通平衡树(fhq Treap)
题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- 洛谷.3391.[模板]文艺平衡树(Splay)
题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...
- [洛谷P1120]小木棍 [数据加强版]
题目大意:有一些同样长的木棍,被切割成几段(长$\leqslant$50).给出每段小木棍的长度,找出原始木棍的最小可能长度. 题解:dfs C++ Code: #include<cstdio& ...
随机推荐
- Java实现 蓝桥杯VIP 算法提高 扫雷
算法提高 扫雷 时间限制:1.0s 内存限制:256.0MB 问题描述 扫雷游戏你一定玩过吧!现在给你若干个n×m的地雷阵,请你计算出每个矩阵中每个单元格相邻单元格内地雷的个数,每个单元格最多有8个相 ...
- iOS-Swift版本自定义CStextView的实现
CSTextView继承自UITextView,并为其增加了placeHolder属性,支持代码和SB方式创建:demo实现了CSTextView的自动排版 效果图 CSTextView地址: htt ...
- Servlet中的请求转发
请求转发时,传递到下一个servlet的request和response可能内存地址不同,但是里面包含的内容是相同的 // servlet1 RequestDispatcher dispatcher ...
- Azure AD(四)知识补充-服务主体
一,引言 又到了新的一周了,也到了我新的分享的时间了,还记得上一周立得Flag,其中 “保证每周输出一篇文章” ,让我特别“在意”(这里用词不太恰当).主要是我的一个大学舍友,他突然问了我一个关于写博 ...
- Nginx源码编译安装选项
[Nginx源码编译过程] make是用来编译的,它从Makefile中读取指令,然后编译. make install是用来安装的,它也从Makefile中读取指令,安装到指定的位置. configu ...
- (七)MySQL常见的数据类型、约束和标识列
一.MySQL常见数据类型 1.数值型: ①整型:tinyint.smllint.mediumint.int/integer.bigint 图源:尚硅谷李玉婷 案例1:关键表格teacher,分别添加 ...
- CSS文本相关之水平排列[4]
在正常流中,文本都是从左往右.自上而下排列显示,如果想要改变排列方向的话,可以通过CSS属性来改变. text-align属性 文本排列(text-align)可改变文本在水平上的方向,但不改变内部的 ...
- K'ed by TNT team是什么意思?
参考资料: https://www.zhihu.com/question/319316132 https://www.reddit.com/r/Piracy/comments/9lk20b/tnt_c ...
- java 拦截器解决xss攻击
一.xss攻击 XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序.这些恶意网页程序通常是JavaScript,但实际上也 ...
- 恕我直言你可能真的不会java第3篇:Stream的Filter与谓词逻辑
一.基础代码准备 建立一个实体类,该实体类有五个属性.下面的代码使用了lombok的注解Data.AllArgsConstructor,这样我们就不用写get.set方法和全参构造函数了.lombok ...