#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#define LL long long
#define LDB long double
using namespace std; LDB alpha=0.75;
const LL mo=;
int newadd;
int root=,datcnt,rbcnt,cnt,nodeintree,delnode;
char ans[];
int nd[],nex[];
int rb[];
LL key[]; struct treenode{
int size,lc,rc,num,fa,tim,v,dep;
LL nam; inline bool operator < (const treenode&a) const {
if (num<a.num) return();
if (num>a.num) return();
if (tim>a.tim) return();
return();
} inline bool operator == (const treenode&a) const{
if ((a.num==num)&&(a.tim==tim)&&(a.nam==nam)) return();
return();
}
}tr[],dat[]; LL namhash(char* st){
LL t=,len=strlen(st);
for (int i=;i<len;i++)
t*=,t+=st[i]-'A'+;
return(t);
} int numget(char* st){
int t=,len=strlen(st);
for (int i=;i<len;i++) t*=,t+=st[i]-'';
return(t);
} void namtrans(LL nam){
int cnt=-;LL t=;
while (t<=nam)
t*=,cnt+=; for (int i=cnt;i>=;i--) ans[i]=nam%+'A'-,nam/=;
for (int i=;i<=cnt;i++) putchar(ans[i]);
} int hash_query(LL nam){
int po=nam%mo;
for (int p=nd[po];p!=-;p=nex[p])
if (key[p]==nam) return(p);
nex[++datcnt]=nd[po];nd[po]=datcnt;key[datcnt]=nam;
newadd=;
return(datcnt);
} int getrank(int po,treenode t){
if ((t==tr[po])&&(tr[po].v!=)) return(tr[tr[po].lc].size+tr[po].v);
if (t<tr[po]) return(getrank(tr[po].lc,t));
if (tr[po]<t) return(getrank(tr[po].rc,t)+tr[tr[po].lc].size+tr[po].v);
} LL getkth(int po,int num){
if (num<=tr[tr[po].lc].size) return(getkth(tr[po].lc,num));
if (num>tr[tr[po].lc].size+tr[po].v) return(getkth(tr[po].rc,num-tr[tr[po].lc].size-tr[po].v));
return(tr[po].nam);
} void dfs(int po){
if (tr[po].lc) dfs(tr[po].lc);
if (tr[po].v) rb[++rbcnt]=po;else nodeintree--,delnode--;
if (tr[po].rc) dfs(tr[po].rc);
} void build(int l,int r){
int mid=(l+r)>>,po=rb[(l+r)/]; if (l<mid){
tr[po].lc=rb[(l+mid-)/];
tr[rb[(l+mid-)/]].fa=po;
tr[rb[(l+mid-)/]].dep=tr[po].dep+;
build(l,mid-);
}else tr[po].lc=;
if (r>mid){
tr[po].rc=rb[(r+mid+)/];
tr[rb[(r+mid+)/]].fa=po;
tr[rb[(r+mid+)/]].dep=tr[po].dep+;
build(mid+,r);
}else tr[po].rc=;
tr[po].size=tr[tr[po].lc].size+tr[tr[po].rc].size+tr[po].v;
} void rebuild(int po){
rbcnt=;dfs(po); if (po!=root){
tr[rb[(rbcnt+)/]].fa=tr[po].fa;
tr[rb[(rbcnt+)/]].dep=tr[tr[po].fa].dep+;
if (po==tr[tr[po].fa].lc) tr[tr[po].fa].lc=rb[(rbcnt+)/];
else tr[tr[po].fa].rc=rb[(rbcnt+)/];
}else {root=rb[(rbcnt+)/];tr[rb[(rbcnt+)/]].fa=;tr[rb[(rbcnt+)/]].dep=;} build(,rbcnt);
} void scapegoat_insert(int num){
nodeintree++;
if ((tr[root].size==)&&(tr[root].lc==)&&(tr[root].rc==)) {
root=++cnt;tr[root]=dat[num];tr[root].dep=;
tr[cnt].v=;tr[cnt].size=;
return;
}
int po=root;
while (){
tr[po].size++; if (dat[num]==tr[po]) {tr[po].v++;break;} if (dat[num]<tr[po]){
if (tr[po].lc==){
tr[++cnt]=dat[num];
tr[cnt].fa=po;
tr[po].lc=cnt;
tr[cnt].dep=tr[po].dep+;
tr[cnt].v=;tr[cnt].size=;
break;
}else {po=tr[po].lc;continue;}
} if (tr[po]<dat[num]){
if (tr[po].rc==){
tr[++cnt]=dat[num];
tr[cnt].fa=po;
tr[po].rc=cnt;
tr[cnt].dep=tr[po].dep+;
tr[cnt].v=;tr[cnt].size=;
break;
}else {po=tr[po].rc;continue;}
}
} if (tr[po].dep>(log(tr[root].size)/log(/alpha))){
int dp=tr[po].dep;
while ((dp-tr[po].dep)<=(log(tr[po].size)/log(/alpha))) po=tr[po].fa;
rebuild(po);
}
} void scapegoat_delete(int num){
int po=root;
while (){
tr[po].size--;
if (tr[po]<dat[num]) {po=tr[po].rc;continue;}
if (dat[num]<tr[po]) {po=tr[po].lc;continue;}
if (tr[po]==dat[num]) {tr[po].v--;if (tr[po].v==) delnode++;break;}
}
if (delnode>nodeintree/) rebuild(root);
} int main(){ freopen("a.in","r",stdin); int n;char st[];
scanf("%d",&n); for (int i=;i<=;i++) nd[i]=-; for (int i=;i<=n;i++){
scanf("%s",st); if (st[]=='+'){
LL nam=namhash(st);
newadd=;
int po=hash_query(nam);
if (!newadd) {
scapegoat_delete(po);
dat[po].nam=nam;scanf("%d",&dat[po].num);dat[po].tim=i;
scapegoat_insert(po);
}else{
dat[po].nam=nam;scanf("%d",&dat[po].num);dat[po].tim=i;
scapegoat_insert(po);
}
} if ((st[]=='?')&&(st[]<='Z')&&(st[]>='A')){
LL nam=namhash(st);
int po=hash_query(nam);
printf("%d\n",datcnt-getrank(root,dat[po])+);
} if ((st[]=='?')&&(st[]<='')&&(st[]>='')){
int po=numget(st);
for (int i=po;i<=min(po+,datcnt);i++) {
namtrans(getkth(root,datcnt-i+));
if (i!=min(po+,datcnt))printf(" ");
}
printf("\n");
}
}
}

替罪羊树模板(BZOJ1056/1862)的更多相关文章

  1. [luogu3369]普通平衡树(替罪羊树模板)

    解题关键:由于需要根据平衡进行重建,所以不能进行去重,否则无法保证平衡性. #include<cstdio> #include<cstring> #include<alg ...

  2. [TYVJ1728/BZOJ3224]普通平衡树-替罪羊树

    Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容 ...

  3. 「BZOJ3600」没有人的算术 替罪羊树+线段树

    题目描述 过长--不想发图也不想发文字,所以就发链接吧-- 没有人的算术 题解 \(orz\)神题一枚 我们考虑如果插入的数不是数对,而是普通的数,这就是一道傻题了--直接线段树一顿乱上就可以了. 于 ...

  4. 平衡树简单教程及模板(splay, 替罪羊树, 非旋treap)

    原文链接https://www.cnblogs.com/zhouzhendong/p/Balanced-Binary-Tree.html 注意是简单教程,不是入门教程. splay 1. 旋转: 假设 ...

  5. 替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

    二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 闲的没事,把各种平衡树都写写 比较比较... 下面是替罪羊树 #include <cstdio> #inc ...

  6. [模板] 平衡树: Splay, 非旋Treap, 替罪羊树

    简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...

  7. 替罪羊树&&非旋treap

    题解: 替罪羊树的模板和splay差距还是比较大的.. 按照我的splay的写法 真是都是问题.. 替罪羊树就是暴力的搞 当某颗子树大小大于这棵树的alpha时 就退出 另外删除的时候打懒标记删除 当 ...

  8. 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)

    在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...

  9. Luogu 3369 / BZOJ 3224 - 普通平衡树 - [替罪羊树]

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 https://www.luogu.org/problemnew/show/P3 ...

随机推荐

  1. Servlet/JSP-04 JSP基础

    一. JSP概述 Servlet 是 Java 程序,可以在 Java 程序内部返回一段 HTML 代码(字符串形式)到浏览器,供浏览器解释展示. JSP 是一种脚本语言,在 HTML 内部通过嵌入 ...

  2. Windows Sever关于80端口之争

    默认情况下安装了IIS服务器角色的Windows系统,其80端口就被占用了.但是占用80端口的进程却不是WWW Service更不是IIS Admin Sevice,而是处于kernel地位的Http ...

  3. ARM 汇编寻址方式

    ARM支持9种寻址方式:立即数寻址,寄存器寻址,寄存器偏移寻址,寄存器间接寻址,基址变址寻址,多寄存器寻址,相对寻址,堆栈寻址,块拷贝寻址. 立即数寻址 将数据直接存放的指令中发给CPU,首先由于AR ...

  4. x01.os.9: 进程切换

    进入内核后,当然不能无所事事.先创建三个进程,分别打印 A,B,C.虽然只是简单的打印,但却是一切扩展的基础,不可等闲视之. 进程切换,涉及一系列的寄存器需要保护,于是,就有了 ProcessStac ...

  5. Ezchip Tilera Tile-Mx100: Der 100-ARM-Netzwerkprozessor

    Ezchip Tilera Tile-Mx100: Der 100-ARM-Netzwerkprozessor ARM-Kerne statt VLIW-Einheiten: Tileras neue ...

  6. 瘟疫公司中国版(Android)手动破解内购

    前言 洒家近日下载了个瘟疫公司中国版(安卓版)(com.easymobi.plagueinc.mi ,版本 1.1.2(5)(.mi 小米版)),发现游戏需要内购而且价格不菲. 需求 root权限 文 ...

  7. shell流程控制

    if语句 判断条件用[]包裹起来 if [ $a > $b ] then echo ‘a > b’ elif [ $a < $b ] then echo ‘a < b’ els ...

  8. windows下nodejs环境配置

    一.下载 去nodejs下载node.msi安装文件包,里面包含了node.js和npm: 双击node.msi就行了,选择安装路径和npm: 二.设置环境变量 [新版本都不需要设计环境变量了,软件会 ...

  9. AI (Adobe Illustrator)详细用法(三)

    本文主要是介绍和色彩相关的用法. 一.路径外观设置 1.设置描边粗细 手动输入20px 下拉选择 鼠标选中数值,按向上或向下的箭头调整 在右边的描边菜单中修改 Note:按住shift键,然后上下箭头 ...

  10. [转]asp.net c# 网上搜集面试题目(附答案)

    本文转自:http://www.cnblogs.com/hndy/articles/2234188.html 1.String str=new String("a")和String ...