模板:替罪羊树
一种平衡树,暴力重构,发现不平衡就重新建树
感谢小红指出我的错误,改完之后发现。。。时间变成了原来的两倍。。。
人丑自带大常数
那么粘一个小红的代码吧,我的时间实在是不太乐观
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const double al=0.7;
struct node
{
node *l,*r;
int val,size,cnt;
bool del;
bool bad()
{
return l->cnt>al*cnt+5||r->cnt>al*cnt+5;
}
void up()
{
size=!del+l->size+r->size;
cnt=1+l->cnt+r->cnt;
}
};
node *null,**badtag;
void dfs(node *k,vector<node*> &v)
{
if(k==null)return ;
dfs(k->l,v);
if(!k->del)v.push_back(k);
dfs(k->r,v);
if(k->del)delete k;
}
node *build(vector<node*> &v,int l,int r)
{
if(l>=r)return null;
int mid=l+r>>1;
node *k=v[mid];
k->l=build(v,l,mid);
k->r=build(v,mid+1,r);
k->up();
return k;
}
void rebuild(node* &k)
{
vector<node*> v;
dfs(k,v);
k=build(v,0,v.size());
}
void insert(int x,node* &k)
{
if(k==null)
{
k=new node;
k->l=k->r=null;
k->del=0;
k->size=k->cnt=1;
k->val=x;
return ;
}
else
{
++k->size;++k->cnt;
if(x>=k->val)insert(x,k->r);
else insert(x,k->l);
if(k->bad())badtag=&k;
else if(badtag!=&null)
k->cnt-=(*badtag)->cnt-(*badtag)->size;
}
}
void ins(int x,node* &k)
{
badtag=&null;
insert(x,k);
if(badtag!=&null)rebuild(*badtag);
}
int getrk(node *now,int x)
{
int ans=1;
while(now!=null)
{
if(now->val>=x)now=now->l;
else
{
ans+=now->l->size+!now->del;
now=now->r;
}
}
return ans;
}
int kth(node *now,int x)
{
while(now!=null)
{
if(!now->del&&now->l->size+1==x)
return now->val;
if(now->l->size>=x)now=now->l;
else
{
x-=now->l->size+!now->del;
now=now->r;
}
}
}
void erase(node *k,int rk)
{
if(!k->del&&rk==k->l->size+1)
{
k->del=1;
--k->size;
return ;
}
--k->size;
if(rk<=k->l->size+!k->del)erase(k->l,rk);
else erase(k->r,rk-k->l->size-!k->del);
}
node *root;int n;
int main()
{
null=new node;
root=null;
scanf("%d",&n);
while(n--)
{
int op,x;
scanf("%d%d",&op,&x);
switch(op)
{
case 1:ins(x,root);break;
case 2:erase(root,getrk(root,x));break;
case 3:printf("%d\n",getrk(root,x));break;
case 4:printf("%d\n",kth(root,x));break;
case 5:printf("%d\n",kth(root,getrk(root,x)-1));break;
case 6:printf("%d\n",kth(root,getrk(root,x+1)));break;
}
}
return 0;
}
算了还是粘一个自己的700ms代码:
#include <vector>
#include <iostream>
#include <cstdio>
using namespace std;
const double alpha = 0.75;
int n, opt, x;
struct node {
node *ls, *rs;
int val, size, cnt;
bool deleted;
bool isbad() { return ls->cnt > alpha * cnt + 5 || rs->cnt > alpha * cnt + 5; }
void maintain() {
size = !deleted + ls->size + rs->size;
cnt = 1 + ls->cnt + rs->cnt;
}
} * null, *root, **badtag;
struct ScapeGoat_Tree {
private:
void dfs(node *k, vector<node *> &v) {
if (k == null)
return;
dfs(k->ls, v);
if (!k->deleted)
v.push_back(k);
dfs(k->rs, v);
if (k->deleted)
delete k;
}
node *build(vector<node *> &v, int l, int r) {
if (l >= r)
return null;
int mid = (l + r) >> 1;
node *k = v[mid];
k->ls = build(v, l, mid);
k->rs = build(v, mid + 1, r);
k->maintain();
return k;
}
void rebuild(node *&k) {
vector<node *> v;
dfs(k, v);
k = build(v, 0, v.size());
}
public:
void insert(int x, node *&k) {
badtag = &null;
if (k == null) {
k = new node;
k->ls = k->rs = null;
k->deleted = false;
k->size = k->cnt = 1;
k->val = x;
return;
} else {
++k->size;
++k->cnt;
if (x >= k->val)
insert(x, k->rs);
else
insert(x, k->ls);
if (k->isbad())
badtag = &k;
else if (badtag == &null)
k->cnt -= (*badtag)->cnt - (*badtag)->size;
}
if (badtag != &null)
rebuild(*badtag);
}
int get_rank(node *k, int x) {
int ans = 1;
while (k != null) {
if (k->val >= x)
k = k->ls;
else {
ans += k->ls->size + !k->deleted;
k = k->rs;
}
}
return ans;
}
int get_kth(node *k, int x) {
while (k != null) {
if (!k->deleted && k->ls->size + 1 == x)
return k->val;
if (k->ls->size >= x)
k = k->ls;
else {
x -= k->ls->size + !k->deleted;
k = k->rs;
}
}
}
void erase(node *k, int rk) {
if (!k->deleted && rk == k->ls->size + 1) {
k->deleted = 1;
--k->size;
return;
}
--k->size;
if (rk <= k->ls->size + !k->deleted)
erase(k->ls, rk);
else
erase(k->rs, rk - k->ls->size - !k->deleted);
}
} SGT;
int main() {
null = new node;
root = null;
scanf("%d", &n);
while (n--) {
scanf("%d%d", &opt, &x);
if (opt == 1)
SGT.insert(x, root);
else if (opt == 2)
SGT.erase(root, SGT.get_rank(root, x));
else if (opt == 3)
printf("%d\n", SGT.get_rank(root, x));
else if (opt == 4)
printf("%d\n", SGT.get_kth(root, x));
else if (opt == 5)
printf("%d\n", SGT.get_kth(root, SGT.get_rank(root, x) - 1));
else if (opt == 6)
printf("%d\n", SGT.get_kth(root, SGT.get_rank(root, x + 1)));
}
}
以普通平衡树为例:
#include<vector>
#include<iostream>
#include<cstdio>
using namespace std;
const double alpha=0.75;
int n,opt,x;
struct node{
node *ls,*rs;
int val,size,cnt;
bool deleted;
bool isbad(){
return ls->cnt>alpha*cnt+5||rs->cnt>alpha*cnt+5;
}
void maintain(){
size=!deleted+ls->size+rs->size;
cnt=1+ls->cnt+rs->cnt;
}
}*null,*root;
struct ScapeGoat_Tree{
private:
void dfs(node *k,vector<node*> &v){
if(k==null) return;
dfs(k->ls,v);
if(!k->deleted) v.push_back(k);
dfs(k->rs,v);
if(k->deleted) delete k;
}
node *build(vector<node*> &v,int l,int r){
if(l>=r) return null;
int mid=(l+r)>>1;
node *k=v[mid];
k->ls=build(v,l,mid);
k->rs=build(v,mid+1,r);
k->maintain();
return k;
}
void rebuild(node* &k){
vector<node*>v;
dfs(k,v);
k=build(v,0,v.size());
}
public:
void insert(int x,node* &k){
if(k==null){
k=new node;
k->ls=k->rs=null;
k->deleted=false;
k->size=k->cnt=1;
k->val=x;
return;
}else{
++k->size;
++k->cnt;
if(x>=k->val)
insert(x,k->rs);
else insert(x,k->ls);
if(k->isbad())rebuild(k);
}
}
int get_rank(node *k,int x){
int ans=1;
while(k!=null){
if(k->val>=x) k=k->ls;
else{
ans+=k->ls->size+!k->deleted;
k=k->rs;
}
}
return ans;
}
int get_kth(node *k,int x){
while(k!=null){
if(!k->deleted && k->ls->size+1==x)
return k->val;
if(k->ls->size>=x) k=k->ls;
else{
x-=k->ls->size+!k->deleted;
k=k->rs;
}
}
}
void erase(node *k,int rk){
if(!k->deleted && rk==k->ls->size+1){
k->deleted=1;
--k->size;
return;
}
--k->size;
if(rk<=k->ls->size+!k->deleted)
erase(k->ls,rk);
else erase(k->rs,rk-k->ls->size-!k->deleted);
}
}SGT;
int x1,y1;
int main(){
null=new node;
root=null;
scanf("%d",&n);
while(n--){
scanf("%d%d",&opt,&x);
if(opt==1) SGT.insert(x,root);
else if(opt==2) SGT.erase(root,SGT.get_rank(root,x));
else if(opt==3) printf("%d\n",SGT.get_rank(root,x));
else if(opt==4) printf("%d\n",SGT.get_kth(root,x));
else if(opt==5) printf("%d\n",SGT.get_kth(root,SGT.get_rank(root,x)-1));
else if(opt==6) printf("%d\n",SGT.get_kth(root,SGT.get_rank(root,x+1)));
}
}

浙公网安备 33010602011771号