洛谷 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& ...
随机推荐
- 第十届蓝桥杯JavaC组省赛真题
试题 A: 求和 本题总分:5 分 [问题描述] 小明对数位中含有 2.0.1.9 的数字很感兴趣,在 1 到 40 中这样的数包 括 1.2.9.10 至 32.39 和 40,共 28 个,他们的 ...
- Java实现 LeetCode 506 相对名次
506. 相对名次 给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌.前三名运动员将会被分别授予 "金牌","银牌" 和" 铜牌&q ...
- Java实现 LeetCode 155 最小栈
155. 最小栈 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) – 将元素 x 推入栈中. pop() – 删除栈顶的元素. top() – 获取 ...
- Java实现蓝桥杯历届试题填字母游戏
题目描述 小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说: "我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了". K大师在纸上画了一行n个格子,要小 ...
- 在已经编译安装好php7场景下,install gd库 with free-type (解决Call to undefined function imagettftext())
在已经编译安装好php7场景下,install gd库 with free-type (解决Call to undefined function imagettftext()) install g ...
- ASP.NET Core Blazor WebAssembly实现一个简单的TODO List
基于blazor实现的一个简单的TODO List 最近看到一些大佬都开始关注blazor,我也想学习一下.做了一个小的demo,todolist,仅是一个小示例,参考此vue项目的实现http:// ...
- KVM在线扩展虚拟机内存
环境介绍 在KVM下有一台虚拟机内存不够需要扩展内存.宿主机地址是192.168.1.28.我需要扩展的虚拟机是centos1708vm03. 1.登陆上宿主机查看虚拟机配置 virsh dumpxm ...
- git提交代码托管平台流程
首先先安装git git官网 ---- https://git-scm.com/ 下载好傻瓜式安装即可 安装好过后,再桌面任意空白区域右键,看到以下两个选项即为安装成功 一般都用第二个选项也就是 Gi ...
- 如何在Centos7安装rabbitmq的PHP扩展
1.先安装rabbitmq-c, wget https://github.com/alanxz/rabbitmq-c/releases/download/v0.8.0/rabbitmq-c-0.8.0 ...
- @loj - 2977@ 「THUSCH 2017」巧克力
目录 @description@ @solution@ @accepted code@ @details@ @description@ 「人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道.」 明 ...