对于区间旋转使用lazy思想就能解决。然后对于区间搬移,先把a-1结点做根,b+1作为它的右孩子,这样ch[ch[root][1]][0]就是区间[a,b],现将他取出。

然后在将当前的树伸展,把c结点转到根,c+1作为它的右孩子,这样c+1结点的左孩子就是空的,直接将上次取出的作为c+1结点的做孩子即可。

#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 99999999
#define ll __int64
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define key_value ch[ch[root][1]][0]
using namespace std;
const int MAXN = *;
int pre[MAXN],ch[MAXN][],siz[MAXN],key[MAXN],rev[MAXN],root,tot1;
int n;
void Treavel(int x)
{
if(x)
{
Treavel(ch[x][]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d key=%2d\n",x,ch[x][],ch[x][],pre[x],siz[x],key[x]);
Treavel(ch[x][]);
}
}
void debug()
{
printf("root:%d\n",root);
Treavel(root);
}
void Newnode(int &rt,int pa,int k)
{
rt = ++tot1;
pre[rt] = pa;
siz[rt] = ;
rev[rt] = ;
key[rt] = k;
ch[rt][] = ch[rt][] = ;
}
void pushup(int rt)
{
siz[rt] = siz[ch[rt][]] + siz[ch[rt][]] + ;
}
void pushdown(int rt)
{
if(rev[rt]){
rev[ch[rt][]] ^= ;
rev[ch[rt][]] ^= ;
swap(ch[rt][],ch[rt][]);
rev[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()
{
tot1 = root = ;
pre[root] = siz[root] = key[root] = rev[root] = ;
ch[root][] = ch[root][] = ;
Newnode(root,,-);
Newnode(ch[root][],root,-);
build(key_value,,n,ch[root][]);
pushup(ch[root][]);
pushup(root);
}
void Rotate(int rt,int kind)
{
int y = pre[rt];
pushdown(y);
pushdown(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);
}
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);
}
}
}
if(goal == )
root = rt;
pushup(rt);
}
int Get_kth(int rt,int k)
{
pushdown(rt);
int t = siz[ch[rt][]] + ;
if(t == k)
return rt;
else if(t > k){
return Get_kth(ch[rt][],k);
}
else {
return Get_kth(ch[rt][],k-t);
}
pushup(rt);
}
void cut(int x,int y,int z)
{
splay(Get_kth(root,x),);
splay(Get_kth(root,y+),root);
//debug();
int tmp = key_value;
key_value = ;
pushup(ch[root][]);
pushup(root);
splay(Get_kth(root,z+),);
splay(Get_kth(root,z+),root);
//debug();
key_value = tmp;
pre[tmp] = ch[root][];
pushup(ch[root][]);
pushup(root);
//debug();
}
int flag;
void display(int rt)
{
if(rt == )
return ;
pushdown(rt);
display(ch[rt][]);
if(!flag && rt != && rt != ){
flag = ;
printf("%d",key[rt]);
}
else if(rt != && rt != ){
printf(" %d",key[rt]);
}
display(ch[rt][]);
}
int main()
{
int i,j,m;
while(~scanf("%d%d",&n,&m),n!=-&&m!=-)
{
Init();
char work[];
while(m--)
{
scanf("%s",work);
if(work[] == 'F'){
int x,y;
scanf("%d%d",&x,&y);
splay(Get_kth(root,x),);
splay(Get_kth(root,y+),root);
rev[key_value] ^= ;
//debug();
}
else {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
cut(x,y,z);
}
}
//debug();
flag = ;
display(root);
cout<<endl;
}
}

hdu3487 伸展树(区间搬移 区间旋转)的更多相关文章

  1. poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)

    好题.我做了很久,学了大牛们的区间搬移.主要的代码都有注释. #include<cstdio> #include<cstring> #include<iostream&g ...

  2. 伸展树splay之求区间极值

    前言 这篇博客是根据我在打这道题的时候遇到的问题,来打的,有些细节可能考虑不到. 题目 在N(1<=N<=100000)个数A1-An组成的序列上进行M(1<=M<=10000 ...

  3. hdu1890 伸展树(区间反转)

    对于大神来说这题是水题.我搞这题花了快2天. 伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交 ...

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

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

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

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

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

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

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

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

  8. POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)

    A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...

  9. poj-----(2528)Mayor's posters(线段树区间更新及区间统计+离散化)

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 43507   Accepted: 12693 ...

随机推荐

  1. Verilog (二) multiplexer and decoder

    1  mutiplexer 数据选择器 1)  one-bit wide 2-1 mux wire dout = sel? din1 : din0; // conditional continuous ...

  2. 怎样用ZBrush中的Curves和Insert笔刷创建四肢

     之前的ZBrush教程给大家介绍了人体结构比例和肌肉走向,同时使用ZBrush®软件中的CuverTube笔刷为模型添加了颈部和手臂.使用InsertSphere笔刷添加腰部,本讲将继续使用Curv ...

  3. 票据OCR前预处理 (附Demo)

    发一个去年做的一个去除票据干扰项的demo,核心处理是移除红色印章,不破坏红印叠加处的文字. 只是一个小小demo,还没具体进行进一步优化. 也不知道什么时候才有精力继续优化它. 现在放出来给大家试用 ...

  4. UESTC 913 握手 Havel定理+优先队列

    给定一个非负整数序列{dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化.进一步,若图为简单图,则称此序列可简单图化. 此题因为是无自环无重边,所以是简单图.用判定简单图可图化 ...

  5. eclipse菜单解释及中英对照《二》

    上篇文章主要介绍了eclipse中每个大的标题下的中英文及其用法. 感谢http://blog.csdn.net/li_jinjian2005/article/details/2831641这个博主. ...

  6. java11-4 字符串的遍历以及字符串中各类字符的统计

    1.需求:获取字符串中的每一个字符   分析: A:如何能够拿到每一个字符呢?  char charAt(int index) B:我怎么知道字符到底有多少个呢? int length() publi ...

  7. Mac快捷键、命令行

    睡眠:option + command + 电源键  立即关机:Cmd-Opt-Ctrl-Eject 立即重启:Cmd-Ctrl-Eject 弹出关机提示 :Ctrl + 关机 正常关机快捷键 : C ...

  8. css3d

    立方体:http://sandbox.runjs.cn/show/1h6zvghj 原理分析:(左负右正) x:与屏幕水平:(在屏幕上) y:与屏幕水平方向垂直(在屏幕上) z:垂直于屏幕(在屏幕外) ...

  9. poj 2245 Lotto

    Lotto Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6806   Accepted: 4298 Description ...

  10. 教你10分钟内在Windows上完成Rails开发环境的安装和配置

    原文:http://www.cnblogs.com/tambor/archive/2011/12/25/rails_anzhuang_railsinstaller.html 一般来说,Windows开 ...