爱死替罪羊树了


这种暴力的数据结构爱死了。什么?!你还不知道替罪羊树?那就看看这篇博客这篇博客吧。替罪羊树就是当不平衡时,拍扁重建,然后就平衡了。想切这道题,要先把普通平衡树那道题做了(这篇博客讲了的哦),然后就会发现,只要改一下以前的程序就可以了。这里我就着重讲下主函数怎么建树那里。

建树方法:

  1. 一开始我写的方法(指读入建树的时候),长一些,详细的都在代码里面了:
#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;
}
  1. 同学写的,短了很多啊,但是似乎我要快一点,我也不知道为什么,可能是因为直接insert的话,数据专门把树卡成链后,重建次数太多,导致要慢一点,而我直接sort快一些(大雾):
for(register int i = 1; i <= n; i++){
x = read();
insert(root , x);
}

吐槽:这道题数据还是有点水吧,比较未加强数据的直接搬过来能AC,可能是为了卡朝鲜树之类的数据结构吧。

洛谷 P6136 【【模板】普通平衡树(数据加强版)】的更多相关文章

  1. 洛谷 P1120 小木棍 [数据加强版]解题报告

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...

  2. 洛谷——P1120 小木棍 [数据加强版]

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍 ...

  3. 洛谷 P1120 小木棍 [数据加强版]

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...

  4. 洛谷 P2241统计方形(数据加强版) 题解

    题目传送门 说是加强版,其实可以把棋盘那道题的代码粘过来(注意要开long long): #include<bits/stdc++.h> using namespace std; ,c; ...

  5. 洛谷—— P1120 小木棍 [数据加强版]

    https://www.luogu.org/problem/show?pid=1120 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接 ...

  6. 洛谷——P2241 统计方形(数据加强版)

    https://www.luogu.org/problem/show?pid=2241 题目背景 1997年普及组第一题 题目描述 有一个n*m方格的棋盘,求其方格包含多少正方形.长方形 输入输出格式 ...

  7. 洛谷.3369.[模板]普通平衡树(Splay)

    题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...

  8. 洛谷.3369.[模板]普通平衡树(fhq Treap)

    题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  9. 洛谷.3391.[模板]文艺平衡树(Splay)

    题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...

  10. [洛谷P1120]小木棍 [数据加强版]

    题目大意:有一些同样长的木棍,被切割成几段(长$\leqslant$50).给出每段小木棍的长度,找出原始木棍的最小可能长度. 题解:dfs C++ Code: #include<cstdio& ...

随机推荐

  1. Java实现 蓝桥杯VIP 算法提高 促销购物

    算法提高 促销购物 时间限制:1.0s 内存限制:256.0MB 问题描述 张超来到了超市购物. 每个物品都有价格,正好赶上商店推出促销方案.就是把许多东西一起买更便宜(保证优惠方案一定比原价便宜). ...

  2. Java实现 LeetCode 101 对称二叉树

    101. 对称二叉树 给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的. 1 / \ 2 2 / \ / \ 3 4 4 3 但是下面这个 [1,2,2 ...

  3. 第八届蓝桥杯JavaB组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.购物单 题目描述 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推 ...

  4. Java实现LeetCode_0013_RomanToInteger

    package javaLeetCode.primary; import java.util.HashMap; import java.util.Map; import java.util.Scann ...

  5. java实现第七届蓝桥杯棋子换位

    棋子换位 棋子换位 有n个棋子A,n个棋子B,在棋盘上排成一行. 它们中间隔着一个空位,用"."表示,比如: AAA.BBB 现在需要所有的A棋子和B棋子交换位置. 移动棋子的规则 ...

  6. vue踩过的坑('url' is assigned a value but never used no-unused-vars)

    1.代码编写 2.遇见错误 3.解决方案 在错误代码后加入注释:(// eslint-disable-line no-unused-vars) 之后页面上就不会出现该错误信息了

  7. 小技巧:如何用 Chrome 将 SVG 转成 PNG

    怎么把 SVG 转成 PNG ?用 Chrome 吧,非常好用,还能设定自己想要的尺寸. 什么是 SVG ? SVG (Scalable Vector Graphics,可缩放矢量图形) 是基于 XM ...

  8. router路由配置

    vue项目中router路由配置   介绍 路由:控制组件之间的跳转,不会实现请求.不用页面刷新,直接跳转-切换组件>>> 安装 本地环境安装路由插件vue-router:    c ...

  9. Unit4-窝窝之昆崚

    全文共3012字,推荐阅读时间10~15分钟. 文章共分五个部分: 作业分析 烘烤OO的精华 评测相关 课程体验感受 一些小小的建议 作业分析 Unit4要求我们实现UML解析器,迭代过程主要是增加对 ...

  10. Dos命令提示符下 - 用sqlcmd执行*.sql语句

    Dos命令提示符下 - 用sqlcmd执行*.sql语句 1)在Dos命令下执行sqlcmd命令(当然事先需要将sqlcmd增加到环境变量中去), 2)下面白色部分替换为服务器名或计算机名即可sqlc ...