替罪羊树在此!!!(你说什么?为什么要写替罪羊树,请看这篇博客,貌似我之前的解释有4,5篇博文吧,希望你有耐心,慢慢看,网址:http://blog.csdn.net/ljf_cnyali/article/details/52588698)
好了,替罪羊树是什么我也不知道(其实我知道),但是我又没有那么大的耐心慢慢写,今天就只写一个模板给你们看看吧,如果有解释的话我把网址再贴给你们:
写得真累,妈妈呀!!!
/*************************************************************************
> File Name: \LJF\模板大全\替罪羊树.cpp
> Author: ljf_cnyali
> Mail: 2724424647@qq.com
> Last modifiedz: 2016-09-19 19:49
> Description: This is a large group of God's program information.
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<ctime>
#include<vector>
using namespace std;
#define REP(i, a, b) for(int i = (a), _end_ = (b);i <= _end_; ++i)
const double IF_OK = 0.75;
const int maxn = 100010;
struct Scapegoat_Tree {
Scapegoat_Tree *l, *r;
int val, size, sum;
bool flag;
void PushUp() {//重新计算
size = r -> size + l -> size + int(flag);
sum = r -> sum + l -> sum + 1;
}
bool IfBad() {//判断是否不符合
return ((r -> sum > sum * IF_OK + 5) || (l -> sum > sum * IF_OK + 5));
}
};
Scapegoat_Tree *root;
void Travel(Scapegoat_Tree *p, vector<Scapegoat_Tree *> &v) {//构建一个序列,维护
if(p == NULL)
return;
Travel(p -> l, v);
if(p -> flag == true)
v.push_back(p);
Travel(p -> r, v);
}
Scapegoat_Tree *Divide(vector<Scapegoat_Tree *> &v, int l, int r) {//插入后维护,要不要重构
if(l >= r)
return NULL;
int mid = (l + r) >> 1;
Scapegoat_Tree *p = v[mid];
p -> l = Divide(v, l, mid);
p -> r = Divide(v, mid + 1, r);
p -> PushUp();
return p;
}
void NewBuild(Scapegoat_Tree *&p) {//重构
static vector<Scapegoat_Tree *> v;
v.clear();
Travel(p, v);
p = Divide(v, 0, v.size());
}
void Insert(Scapegoat_Tree *&p, int key) {//插入
if(p == NULL) {
p -> l = p -> r = NULL;
p -> size = p -> sum = 1;
p -> flag = true;
p -> val = key;
return;
}
else {
p -> size++;
p -> sum++;
if(p -> val > key)
Insert(p -> l, key);
else
Insert(p -> r, key);
if(p -> IfBad())
NewBuild(*&p);
}
}
void Erase(Scapegoat_Tree *p, int id) {//貌似是删除
p -> sum--;
int off = p -> l -> sum + int(p -> flag);
if(p -> flag == true && id == off) {
p -> flag = false;
return;
}
else {
if(id <= off)
Erase(p -> l, id);
else
Erase(p -> r, id - off);
}
if(p == root)
if(root -> size < IF_OK * root -> sum)
NewBuild(root);
}
void INIT() {
root -> l = root -> r = NULL;
root -> sum = root -> size = root -> val = 0;
}
int Rank(int key) {//求key是第几个
Scapegoat_Tree *p = root;
int ans = 1;
while(p != NULL) {
if(p -> val >= key)
p = p -> l;
else {
ans += p -> l -> size + p -> flag;
p = p -> r;
}
}
return ans;
}
int Rand_K(int k) {//求排名为k的大小
Scapegoat_Tree * p = root;
while(p != NULL) {
if(p -> l -> size + 1 == k && p -> flag)
return p -> val;
else if(p -> l -> size >= k)
p = p -> l;
else {
k -= p -> l -> size + p -> flag;
p = p -> r;
}
}
}
int main() {
/*
前面都有注释,接下来直接调用就好了。
写这个真的累,再也不想玩这些了。。。
*/
return 0;
}