#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAXN 100010
struct Node{
int key, sz, cnt; //cnt表示结点值为key的结点的数量
Node *ch[2], *pnt;//左右儿子和父亲
Node(){} //给Node函数赋值。
Node(int x, int y, int z){
key = x, sz = y, cnt = z;
}
void rs(){//这个函数的含义就是旋转后,这2个结点的大小已经发生了改变
sz = ch[0]->sz + ch[1]->sz + cnt;
}
}nil(0, 0, 0), *NIL = &nil;
struct Splay{//伸展树结构体类型
Node *root;
int ncnt;//计算key值不同的结点数,注意已经去重了*
Node nod[MAXN];
void init(){// 首先要初始化*
root = NIL;
ncnt = 0;
}
void rotate(Node *x, bool d){//旋转操作,d为true表示右旋
Node *y = x->pnt;
y->ch[!d] = x->ch[d];//x右旋的时候,y的左儿子为x的右边儿
if (x->ch[d] != NIL)//如果x的右儿子不为空那么这个右儿子的父亲是y
x->ch[d]->pnt = y;
x->pnt = y->pnt;//把y的父亲赋值给x的父亲,相当x替代了y的位子
if (y->pnt != NIL){//把y的父亲的左儿子或右儿子从y改为x
if (y == y->pnt->ch[d])
y->pnt->ch[d] = x;
else
y->pnt->ch[!d] = x;
}
x->ch[d] = y;
y->pnt = x;
y->rs();
x->rs();
}
void splay(Node *x, Node *target){//将x伸展到target的儿子位置处
Node *y;
while (x->pnt != target){ //当target时,就转x为根结点
y = x->pnt;
if (x == y->ch[0]){
if (y->pnt != target && y == y->pnt->ch[0])//如果x是y的左结点,且y的父亲结点不是目标结点
rotate(y, true);//并且y是y的左结点才旋转y否则旋转x
rotate(x, true);
}
else{
if (y->pnt != target && y == y->pnt->ch[1])
rotate(y, false);
rotate(x, false);
}
}
if (target == NIL)
root = x;
}
/************************以上一般不用修改************************/
void insert(int key){//插入一个值
if (root == NIL){//初始化根节点
ncnt = 0;
root = &nod[++ncnt];
root->ch[0] = root->ch[1] = root->pnt = NIL;
root->key = key; //这里表示这个结点的值
root->sz = root->cnt = 1;//sz表示这个结点作为根的大小
return;
}
Node *x = root, *y;
while (1){ //从x开始向下找,刚开始x就是root
x->sz++;
if (key == x->key){
x->cnt++;
x->rs();
y = x;
break;
}
else if (key < x->key){//这里表示如果新加入的值比x小,且左结点为空,那么就加入其作为左儿子
if (x->ch[0] != NIL)//否则接着往左边找
x = x->ch[0];
else{//且左结点为空,那么就加入其作为左儿子
x->ch[0] = &nod[++ncnt];
y = x->ch[0];//新加入的点为y
y->key = key;
y->sz = y->cnt = 1;//y的刚开始大小为1
y->ch[0] = y->ch[1] = NIL;//左右子树均为NIL
y->pnt = x;//
break;
}
}
else{
if (x->ch[1] != NIL)
x = x->ch[1];
else{
x->ch[1] = &nod[++ncnt];
y = x->ch[1];
y->key = key;
y->sz = y->cnt = 1;
y->ch[0] = y->ch[1] = NIL;
y->pnt = x;
break;
}
}
}
splay(y, NIL);
}
Node* search(int key){//查找一个值并且把这个值旋上来,返回指针
if (root == NIL)
return NIL;
Node *x = root, *y = NIL;
while (1){
if (key == x->key){
y = x;
break;
}
else if (key > x->key){
if (x->ch[1] != NIL)
x = x->ch[1];
else
break;
}
else{
if (x->ch[0] != NIL)
x = x->ch[0];
else
break;
}
}
splay(x, NIL);
return y;
}
Node* searchmin(Node *x){//查找最小值,返回指针
Node *y = x->pnt;
while (x->ch[0] != NIL){//遍历到最左的儿子就是最小值
x = x->ch[0];
}
splay(x, y);
return x;
}
void del(int key){//删除一个值
if (root == NIL)
return;
Node *x = search(key), *y;
if (x == NIL)
return;
if (x->cnt > 1){ //如果这个结点还有,那么它就变成根结点
x->cnt--;
x->rs();
return;
}
else if (x->ch[0] == NIL && x->ch[1] == NIL){ //这个是最后一个结点
init();
return;
}
else if (x->ch[0] == NIL){
root = x->ch[1];
x->ch[1]->pnt = NIL;
return;
}
else if (x->ch[1] == NIL){
root = x->ch[0];
x->ch[0]->pnt = NIL;
return;
}
y = searchmin(x->ch[1]);
y->pnt = NIL;
y->ch[0] = x->ch[0];
x->ch[0]->pnt = y;
y->rs();
root = y;
}
int rank(int key){//???这里看不懂,求结点高度
Node *x = search(key);
if (x == NIL)
return 0;
return x->ch[0]->sz + 1;/* or x->cnt*/
}
Node* findk(int kth){//查找第k小的值
if (root == NIL || kth > root->sz)
return NIL;
Node *x = root;
while (1){
if (x->ch[0]->sz +1 <= kth && kth <= x->ch[0]->sz + x->cnt)
break;
else if (kth <= x->ch[0]->sz)
x = x->ch[0];
else{
kth -= x->ch[0]->sz + x->cnt;
x = x->ch[1];
}
}
splay(x, NIL);
return x;
}
}sp;
int main(){ //每次sp的返回都是一个指针
sp.init();
sp.insert(10);
sp.insert(2);
sp.insert(2);
sp.insert(2);
sp.insert(3);
sp.insert(3);
sp.insert(10);
for (int i = 1; i <= 7; i++)
cout << sp.findk(i)->key << endl;
cout<< "最小值是"<<sp.searchmin(sp.root)->key<<endl;
sp.del(2);
sp.del(3);
sp.del(1);
cout << "不同结点的数量"<<sp.ncnt << endl;
cout << "这棵树的大小 " << sp.root->sz << endl;
return 0;
}
这个代码是一个模版。
下面是区间求最大值,反转
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=100005, INF=0x7fffffff;
struct Splay_Tree {
struct Node {
int val, Max, add, Size, son[2];
bool rev;
void init(int _val) {
val=Max=_val, Size=1;
add=rev=son[0]=son[1]=0;
}
} T[N];
int fa[N], root;
void pushUp(int x) {
T[x].Max=T[x].val, T[x].Size=1;
if(T[x].son[0]) {
T[x].Max=max(T[x].Max, T[T[x].son[0]].Max);
T[x].Size+=T[T[x].son[0]].Size;
}
if(T[x].son[1]) {
T[x].Max=max(T[x].Max, T[T[x].son[1]].Max);
T[x].Size+=T[T[x].son[1]].Size;
}
}
void pushDown(int x) {
if(x==0) return;
if(T[x].add) {
if(T[x].son[0]) {
T[T[x].son[0]].val+=T[x].add;
T[T[x].son[0]].Max+=T[x].add;
T[T[x].son[0]].add+=T[x].add;
}
if(T[x].son[1]) {
T[T[x].son[1]].val+=T[x].add;
T[T[x].son[1]].Max+=T[x].add;
T[T[x].son[1]].add+=T[x].add;
}
T[x].add=0;
}
if(T[x].rev) {
if(T[x].son[0]) T[T[x].son[0]].rev^=1;
if(T[x].son[1]) T[T[x].son[1]].rev^=1;
swap(T[x].son[0], T[x].son[1]);
T[x].rev=0;
}
}
void Rotate(int x, int kind) {
int y=fa[x], z=fa[y];
T[y].son[!kind]=T[x].son[kind], fa[T[x].son[kind]]=y;
T[x].son[kind]=y, fa[y]=x;
T[z].son[T[z].son[1]==y]=x, fa[x]=z;
pushUp(y);
}
void Splay(int x, int goal) {
if(x==goal) return;
while(fa[x]!=goal) {
int y=fa[x], z=fa[y];
pushDown(z), pushDown(y), pushDown(x);
int rx=T[y].son[0]==x, ry=T[z].son[0]==y;
if(z==goal) Rotate(x, rx);
else {
if(rx==ry) Rotate(y, ry);
else Rotate(x, rx);
Rotate(x, ry);
}
}
pushUp(x);
if(goal==0) root=x;
}
int Select(int pos) {
int u=root;
pushDown(u);
while(T[T[u].son[0]].Size!=pos) {
if(pos<T[T[u].son[0]].Size) u=T[u].son[0];
else {
pos-=T[T[u].son[0]].Size+1;
u=T[u].son[1];
}
pushDown(u);
}
return u;
}
void update(int L, int R, int val) {
int u=Select(L-1), v=Select(R+1);
Splay(u, 0);
Splay(v, u);
T[T[v].son[0]].Max+=val;
T[T[v].son[0]].val+=val;
T[T[v].son[0]].add+=val;
}
void Reverse(int L, int R) {
int u=Select(L-1), v=Select(R+1);
Splay(u, 0);
Splay(v, u);
T[T[v].son[0]].rev^=1;
}
int query(int L, int R) {
int u=Select(L-1), v=Select(R+1);
Splay(u, 0);
Splay(v, u);
return T[T[v].son[0]].Max;
}
int build(int L, int R) {
if(L>R) return 0;
if(L==R) return L;
int mid=(L+R)>>1, sL, sR;
T[mid].son[0]=sL=build(L, mid-1);
T[mid].son[1]=sR=build(mid+1, R);
fa[sL]=fa[sR]=mid;
pushUp(mid);
return mid;
}
void init(int n) {
T[0].init(-INF), T[1].init(-INF), T[n+2].init(-INF);
for(int i=2; i<=n+1; i++) T[i].init(0);
root=build(1, n+2), fa[root]=0;
fa[0]=0, T[0].son[1]=root, T[0].Size=0;
}
};
Splay_Tree hehe;
int main() {
int n, m;
scanf("%d%d", &n, &m);
hehe.init(n);
for(int i=0, a, b, c, d; i<m; i++) {
scanf("%d", &a);
if(a==1) {
scanf("%d%d%d", &b, &c, &d);
hehe.update(b, c, d);
}
else if(a==2) {
scanf("%d%d", &b, &c);
hehe.Reverse(b, c);
}
else {
scanf("%d%d", &b, &c);
printf("%d\n", hehe.query(b, c));
}
}
return 0;
}