bryce1010专题训练——Splay树
| Prob | Hint | 
|---|---|
| BZOJ 3323 文艺平衡树 | 区间翻转 | 
| BZOJ 1251 序列终结者 | 区间翻转,询问最值 | 
| BZOJ 1895 supermemo | 区间加,翻转,剪切,询问最值。点插入,删除。 | 
| BZOJ 1056 排名系统 | 专治操作完不伸展 | 
| BZOJ 1552 robotic sort | 区间反转,清除标记,splay 的灵活运用 | 
| BZOJ 3224 普通平衡树 | 像普通平衡树一样使用 Splay | 
1、查找区间第K大+排序 
http://acm.hdu.edu.cn/showproblem.php?pid=1890【HDU1890】
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define Key_value ch[ch[root][1]][0]
const int MAXN = 100010;
int pre[MAXN],ch[MAXN][2],root,tot1;
int size[MAXN];//子树规模
int rev[MAXN];//反转标记
int s[MAXN],tot2;//内存池和容量
//debug部分**********************************
void Treavel(int x)
{
    if(x)
    {
        Treavel(ch[x][0]);
        printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d rev = %2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],rev[x]);
        Treavel(ch[x][1]);
    }
}
void debug()
{
    printf("root:%d\n",root);
    Treavel(root);
}
//以上是debug部分**************************************
void NewNode(int &r,int father,int k)
{
    r = k;
    pre[r] = father;
    ch[r][0] = ch[r][1] = 0;
    size[r] = 1;
    rev[r] = 0;
}
//反转的更新
void Update_Rev(int r)
{
    if(!r)return;
    swap(ch[r][0],ch[r][1]);
    rev[r] ^= 1;
}
inline void push_up(int r)
{
    size[r] = size[ch[r][0]] + size[ch[r][1]] + 1;
}
inline void push_down(int r)
{
    if(rev[r])
    {
        Update_Rev(ch[r][0]);
        Update_Rev(ch[r][1]);
        rev[r] = 0;
    }
}
void Build(int &x,int l,int r,int father)
{
    if(l > r)return;
    int mid = (l+r)/2;
    NewNode(x,father,mid);
    Build(ch[x][0],l,mid-1,x);
    Build(ch[x][1],mid+1,r,x);
    push_up(x);
}
int n;
void Init()
{
    root = tot1 = tot2 = 0;
    ch[root][0] = ch[root][1] = pre[root] = size[root] = rev[root] = 0;
    NewNode(root,0,n+1);
    NewNode(ch[root][1],root,n+2);
    Build(Key_value,1,n,ch[root][1]);
    push_up(ch[root][1]);
    push_up(root);
}
//旋转,0为左旋,1为右旋
inline void Rotate(int x,int kind)
{
    int y = pre[x];
    push_down(y);
    push_down(x);//先把y的标记下传,在把x的标记下传
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if(pre[y])
        ch[pre[y]][ch[pre[y]][1]==y] = x;
    pre[x] = pre[y];
    ch[x][kind] = y;
    pre[y] = x;
    push_up(y);
}
//Splay调整,将r结点调整到goal下面
inline void Splay(int r,int goal)
{
    push_down(r);
    while(pre[r] != goal)
    {
        if(pre[pre[r]] == goal)
        {
            //有反转操作,需要先push_down,再判断左右孩子
            push_down(pre[r]);
            push_down(r);
            Rotate(r,ch[pre[r]][0]==r);
        }
        else
        {
            //有反转操作,需要先push_down
            push_down(pre[pre[r]]);
            push_down(pre[r]);
            push_down(r);
            int y = pre[r];
            int kind = ch[pre[y]][0]==y;
            if(ch[y][kind] == r)
            {
                Rotate(r,!kind);
                Rotate(r,kind);
            }
            else
            {
                Rotate(y,kind);
                Rotate(r,kind);
            }
        }
    }
    push_up(r);
    if(goal == 0) root = r;
}
//得到第k个结点(需要push_down)
inline int Get_kth(int r,int k)
{
    push_down(r);
    int t = size[ch[r][0]] + 1;
    if(t == k)return r;
    if(t > k)return Get_kth(ch[r][0],k);
    else return Get_kth(ch[r][1],k-t);
}
//找前驱(需要push_down)
inline int Get_pre(int r)
{
    push_down(r);
    if(ch[r][0] == 0)return -1;//不存在
    r = ch[r][0];
    while(ch[r][1])
    {
        r = ch[r][1];
        push_down(r);
    }
    return r;
}
//找后继(需要push_down)
inline int Get_next(int r)
{
    push_down(r);
    if(ch[r][1] == 0)return -1;
    r = ch[r][1];
    while(ch[r][0])
    {
        r = ch[r][0];
        push_down(r);
    }
    return r;
}
struct Node
{
    int id,val;
}node[MAXN];
bool cmp(Node a,Node b)
{
    if(a.val != b.val)return a.val < b.val;
    else return a.id < b.id;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
     while(scanf("%d",&n) == 1 && n)
    {
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&node[i].val);
            node[i].id = i;
        }
        sort(node+1,node+n+1,cmp);
        Init();
        for(int i = 1; i <= n;i++)
        {
            Splay(node[i].id,0);
            printf("%d",size[ch[root][0]]);
            if(i < n)printf(" ");
            else printf("\n");
            Splay(Get_kth(root,i),0);
            Splay(Get_next(node[i].id),root);
            Update_Rev(Key_value);
        }
    }
    return 0;
}
												
											bryce1010专题训练——Splay树的更多相关文章
- bryce1010专题训练——LCT&&树链剖分
		
LCT&&树链剖分专题 参考: https://blog.csdn.net/forever_wjs/article/details/52116682
 - bryce1010专题训练——划分树
		
1.求区间第K大 HDU2665 Kth number /*划分树 查询区间第K大 */ #include<iostream> #include<stdio.h> #inclu ...
 - bryce1010专题训练——线段树习题汇总
		
一.区间查询,无单点更新 hdu2795 Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 ...
 - bryce1010专题训练——树状数组
		
Bryce1010模板 1.一维树状数组 https://vjudge.net/contest/239647#problem/A[HDU1556] #include<bits/stdc++.h& ...
 - bryce1010专题训练——CDQ分治
		
Bryce1010模板 CDQ分治 1.与普通分治的区别 普通分治中,每一个子问题只解决它本身(可以说是封闭的) 分治中,对于划分出来的两个子问题,前一个子问题用来解决后一个子问题而不是它本身 2.试 ...
 - Leedcode算法专题训练(树)
		
递归 一棵树要么是空树,要么有两个指针,每个指针指向一棵树.树是一种递归结构,很多树的问题可以使用递归来处理. 1. 树的高度 104. Maximum Depth of Binary Tree (E ...
 - bryce1010专题训练——LCA
		
1.Targan算法(离线) http://poj.org/problem?id=1470 /*伪代码 Tarjan(u)//marge和find为并查集合并函数和查找函数 { for each(u, ...
 - dp专题训练
		
****************************************************************************************** 动态规划 专题训练 ...
 - DP专题训练之HDU 2955 Robberies
		
打算专题训练下DP,做一道帖一道吧~~现在的代码风格完全变了~~大概是懒了.所以.将就着看吧~哈哈 Description The aspiring Roy the Robber has seen a ...
 
随机推荐
- 如何刷新本地的DNS缓存?
			
为了提高网站的访问速度,系统会在成功访问某网站后将该网站的域名.IP地址信息缓存到本地.下次访问该域名时直接通过IP进行访问.一些网站的域名没有变化,但IP地址发生变化,有可能因本地的DNS缓存没有刷 ...
 - html5--5-4 绘制矩形
			
html5--5-4 绘制矩形 学习要点 掌握绘制矩形的方法:strkeRect()/fillRect() 掌握绘制路径的 beginPath()和closePath() 矩形的绘制方法 rect(x ...
 - Eclipse 插件使用
			
1. AmaterasUML:UML 类图(class diagram) 注意这里是先编写好代码,通过插件根据代码逻辑关系生成类图: 安装AmaterasUML前,需要先安装 GEF,采用 eclip ...
 - 「LuoguP4147」 玉蟾宫(并查集
			
题目背景 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. 题目描述 这片土地被分成N*M个格子,每个格子里写着'R'或者'F ...
 - AtCoder Grand Contest 012 C:Tautonym Puzzle
			
题目传送门:https://agc012.contest.atcoder.jp/tasks/agc012_c 题目翻译 如果一个字符串是好的,那么这个字符串的前半部分和后半部分肯定一模一样.比如\(a ...
 - 魔法少女-dp
			
魔法少女 Time Limit: 1000MS Memory Limit: 65535KB 64bit IO Format: %I64d & %I64u 前些时间虚渊玄的巨献小圆着实火 ...
 - JAVA 内部类 (二)
			
一.为什么要使用内部类 为什么要使用内部类?在<Think in java>中有这样一句话:使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继 ...
 - Qt工程pro文件的简单配置(尤其是第三方头文件和库)
			
Qt开发中,pro文件是对正工程所有源码.编译.资源.目录等的全方位配置的唯一方式,pro文件的编写非常重要,以下对几个重要项进行说明(win和linux,mac平台通用配置) 注释 以”#”开始的行 ...
 - 蓝桥杯 2014本科C++ B组 六角填数 枚举排列
			
标题:六角填数 如图[1.png]所示六角形中,填入1~12的数字. 使得每条直线上的数字之和都相同. 图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少? 请通过浏览器提交答案,不要填 ...
 - 5.oracle中一个字段中存储'a','b'与'a'与a的写法,存储过程中与之对应
			
select '''a'',''b''' from dual; --'a','b' select '''a''' from dual; --'a' select 'a' from dual; --a