对于大神来说这题是水题。我搞这题花了快2天。

  伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交换左右

子树就可以了(中序),根结点的位置就是i+siz[ch[root][0]],i是处理完的结点个数,siz[ch[root][0]]就是左子树(需要旋转的个数)。 旋转可以用lazy思想标记,这样时间就为logn了。由于第k大的值已经处理完成,所以直接将根结点删除。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define key_value ch[ch[root][1]][0]
using namespace std;
const int MAXN = ;
struct node
{
int id;
int v;
}a[MAXN];
int pre[MAXN],ch[MAXN][],siz[MAXN],lazy[MAXN],tot1,root;
int s[MAXN],tot2,n;
bool cmp(node fa,node fb)
{
if(fa.v != fb.v)
return fa.v < fb.v;
return fa.id < fb.id;
}
void Treavel(int x)
{
if(x)
{
Treavel(ch[x][]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,lazy=%2d\n",x,ch[x][],ch[x][],pre[x],siz[x],lazy[x]);
Treavel(ch[x][]);
}
}
void debug()
{
printf("root:%d\n",root);
Treavel(root);
}
void Newnode(int &rt,int pa,int k)
{
rt = k;
pre[rt] = pa;
siz[rt] = ;
lazy[rt] = ;
ch[rt][] = ch[rt][] = ;
}
void pushup(int rt)
{
siz[rt] = siz[ch[rt][]] + siz[ch[rt][]] + ;
}
void pushdown(int rt)
{
if(lazy[rt]){
lazy[ch[rt][]] ^= ;
lazy[ch[rt][]] ^= ;
swap(ch[rt][],ch[rt][]);
lazy[rt] = ;
}
}
void build(int &rt,int l,int r,int pa)
{
if(l > r){
return ;
}
int m = (l+r)/;
Newnode(rt,pa,m);
build(ch[rt][],l,m-,rt);
build(ch[rt][],m+,r,rt);
pushup(rt);
}
void Init()
{
root = tot1 = tot2 = ;
ch[root][] = ch[root][] = siz[root] = lazy[root] = pre[root] = ;
build(root,,n,);
pushup(root);
}
void Rotate(int rt,int kind)
{
pushdown(pre[rt]);
pushdown(rt);
int y = pre[rt];
ch[y][!kind] = ch[rt][kind];
pre[ch[rt][kind]] = y;
if(pre[y]){
ch[pre[y]][ch[pre[y]][]==y] = rt;
}
pre[rt] = pre[y];
ch[rt][kind] = y;
pre[y] = rt;
pushup(y);
pushup(rt);
}
void splay(int rt,int goal)
{
pushdown(rt);
while(pre[rt] != goal)
{
if(pre[pre[rt]] == goal){
pushdown(pre[rt]);
pushdown(rt);
Rotate(rt,ch[pre[rt]][]==rt);
}
else {
pushdown(pre[pre[rt]]);
pushdown(pre[rt]);
pushdown(rt);
int y = pre[rt];
int kind = ch[pre[y]][]==y;
if(ch[y][kind] == rt){
Rotate(rt,!kind);
Rotate(rt,kind);
}
else {
Rotate(y,kind);
Rotate(rt,kind);
}
}
}
pushup(rt);
if(goal == )
root = rt; }
int Get_max(int rt)
{
pushdown(rt);
while(ch[rt][]){
rt = ch[rt][];
pushdown(rt);
}
return rt;
}
void del(int root)
{
if(ch[root][] == ){
root = ch[root][];
pre[root] = ;
}
else {
int t = Get_max(ch[root][]);
splay(t,root);
ch[t][] = ch[root][];
pre[ch[root][]] = t;
root = t;
pre[root] = ;
pushup(root);
}
}
int main()
{
int i;
while(~scanf("%d",&n),n)
{
for(i=; i<=n; i++){
scanf("%d",&a[i].v);
a[i].id = i;
}
sort(a+,a+n+,cmp);
Init(); for(i=; i<=n; i++){
//cout<<"test1: "<<endl; splay(a[i].id,);
// debug();
lazy[ch[root][]] ^= ;
printf("%d",i+siz[ch[root][]]);
if(i < n)printf(" ");
else printf("\n");
del(root); }
}
}

hdu1890 伸展树(区间反转)的更多相关文章

  1. 2018牛客网暑期ACM多校训练营(第三场) H - Shuffle Cards - [splay伸展树][区间移动][区间反转]

    题目链接:https://www.nowcoder.com/acm/contest/141/C 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...

  2. [置顶] hdu 1890 伸展树区间翻转

    题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...

  3. POJ 3468 A Simple Problem with Integers (伸展树区间更新求和操作 , 模板)

    伸展数最基本操作的模板,区间求和,区间更新.为了方便理解,特定附上一自己搞的搓图 这是样例中的数据输入后建成的树,其中的1,2是加入的边界顶点,数字代表节点编号,我们如果要对一段区间[l, r]进行操 ...

  4. POJ3580 SuperMemo splay伸展树,区间操作

    题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次, ...

  5. PHP算法 《树形结构》 之 伸展树(1) - 基本概念

    伸展树的介绍 1.出处:http://dongxicheng.org/structure/splay-tree/ A. 概述 二叉查找树(Binary Search Tree,也叫二叉排序树,即Bin ...

  6. Splay伸展树入门(单点操作,区间维护)附例题模板

    Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...

  7. hdu 1754 splay tree伸展树 初战(单点更新,区间属性查询)

    题意:与区间查询点更新,点有20W个,询问区间的最大值.曾经用线段树,1000+ms,今天的伸展树,890没ms,差不多. 第一次学习伸展树,一共花了2个单位时间,感觉伸展树真很有用,也很好玩.现在只 ...

  8. 算法模板——splay区间反转 2

    实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没 ...

  9. 伸展树Splay【非指针版】

    ·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...

随机推荐

  1. 如何对ZBrush中面部进行快速布线

    面部布线的最重要目的是为了表情动画.人物内心的各种不同的心里活动,主要是通过面部表情反映出来.而面部变化最丰富的地方是眼部(眉毛)和口 部,其他部位则相应的会受这两部分的影响而变化.对于面部表情,必须 ...

  2. hihocoder-1389&&2016北京网赛07 Sewage Treatment(二分+网络流)

    题目链接: Sewage Treatment 时间限制:2000ms 单点时限:2000ms 内存限制:256MB 描述 After years of suffering, people could ...

  3. 2014 Super Training #10 C Shadow --SPFA/随便搞/DFS

    原题: FZU 2169 http://acm.fzu.edu.cn/problem.php?pid=2169 这题貌似有两种解法,DFS和SPFA,但是DFS怎么都RE,SPFA也要用邻接表表示边, ...

  4. Git版本控制工具(三)----远程仓库GitHub的使用

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  5. 本地不安装Oracle,plsql远程连接数据库

    由于Oracle的庞大,有时候我们需要在只安装Oracle客户端如plsql.toad等的情况下去连接远程数据库,可是没有安装Oracle就没有一切的配置文件去支持.最后终于发现一个很有效的方法,Or ...

  6. Eclipse去除JavaScript验证错误

    这篇文章主要是对Eclipse去除js(JavaScript)验证错误进行了介绍.在Eclipse中,js文件常常会报错.可以通过如下几个步骤解决 第一步: 去除eclipse的JS验证: 将wind ...

  7. 查询OOP课程

    --检测有没有名称为MySchool的数据库 use master if exists (select * from sysdatabases where name='myschool') begin ...

  8. 用运算符代替if、else

  9. table标签去除默认边框

    table去除默认边框 1.在没有出去默认边框时,改变底部颜色,依然显示1px左右的白色边框 2.为table 加上 border="0" cellpadding="0& ...

  10. 12Spring_AOP编程(AspectJ)_前置通知

    接下里的博客会一篇一篇的讲解每一个通知.其实AOP_AspectJ的编程与传统的AOP的编程的最大的区别就是写一个Aspect 支持多个Advice和多个PointCut .而且我们写AOP_Aspc ...