对于区间旋转使用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. 初始化httpclient的几种方式

    1.CloseableHttpClient httpclient = HttpClients.createDefault(); 2.DefaultHttpClient client = new Def ...

  2. 初识selenium-grid

    什么是selenium-grid,官方解释:takes Selenium Remote Control to another level by running tests on many server ...

  3. 边工作边刷题:70天一遍leetcode: day 85-3

    Zigzag Iterator 要点: 实际不是zigzag而是纵向访问 这题可以扩展到k个list,也可以扩展到只给iterator而不给list.结构上没什么区别,iterator的hasNext ...

  4. WPF标注装饰器

    标注 在许多地方我们都会用到标注,比如在画图中: 在Office中: 在Foxit Reader中: 在Blend中: 等等. 简介 以前,因项目上需要做标注,简单找了一下,没发现适合要求的控件(包括 ...

  5. Params 方法参数

    params,ref,out 方法参数 示例 在下面的方法使用中 OpenWindow(params object[] args) 传递的参数args添加了params修饰 public void O ...

  6. 从Maya中导入LightMap到unity中

    导入步骤 1.在Maya中为每一个模型烘焙好帖图(tif格式),会发现烘焙好的图和UV是一一对应的 2.把模型和烘焙帖图导入到Unity中 3.选中材质,修改Shader为 Legacy Shader ...

  7. QC学习三:Excel数据导入导出QC操作流程

    环境: QC9 WindowsXP Office2007   1. 准备 1.通过Excel导入QC,需要下载Microsoft Excel Add-in: http://update.externa ...

  8. MySchool

    USE [MySchool] GO /****** Object: Table [dbo].[Grade] Script Date: 08/06/2014 15:03:17 ******/ SET A ...

  9. 16进制色值转换成RGB

    #51147f  转换成RGB ,5*16+1 ,1*16+4,7*16+15 #A9A9A9 转换成RGB ,A*16+9 ,A*16+9,A*16+9

  10. 查询各个商品分类中各有多少商品的SQL语句

    SELECT goods_category_id ,count(*) FROM `sw_goods` group by goods_category_id