hdu3487 伸展树(区间搬移 区间旋转)
对于区间旋转使用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 伸展树(区间搬移 区间旋转)的更多相关文章
- poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)
好题.我做了很久,学了大牛们的区间搬移.主要的代码都有注释. #include<cstdio> #include<cstring> #include<iostream&g ...
- 伸展树splay之求区间极值
前言 这篇博客是根据我在打这道题的时候遇到的问题,来打的,有些细节可能考虑不到. 题目 在N(1<=N<=100000)个数A1-An组成的序列上进行M(1<=M<=10000 ...
- hdu1890 伸展树(区间反转)
对于大神来说这题是水题.我搞这题花了快2天. 伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交 ...
- POJ 3468 A Simple Problem with Integers (伸展树区间更新求和操作 , 模板)
伸展数最基本操作的模板,区间求和,区间更新.为了方便理解,特定附上一自己搞的搓图 这是样例中的数据输入后建成的树,其中的1,2是加入的边界顶点,数字代表节点编号,我们如果要对一段区间[l, r]进行操 ...
- [置顶] hdu 1890 伸展树区间翻转
题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...
- Splay伸展树入门(单点操作,区间维护)附例题模板
Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...
- hdu 1754 splay tree伸展树 初战(单点更新,区间属性查询)
题意:与区间查询点更新,点有20W个,询问区间的最大值.曾经用线段树,1000+ms,今天的伸展树,890没ms,差不多. 第一次学习伸展树,一共花了2个单位时间,感觉伸展树真很有用,也很好玩.现在只 ...
- POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)
A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...
- poj-----(2528)Mayor's posters(线段树区间更新及区间统计+离散化)
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 43507 Accepted: 12693 ...
随机推荐
- codeforces 721B B. Passwords(贪心)
题目链接: B. Passwords time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- HDU 4454 Stealing a Cake --枚举
题意: 给一个点,一个圆,一个矩形, 求一条折线,从点出发,到圆,再到矩形的最短距离. 解法: 因为答案要求输出两位小数即可,精确度要求不是很高,于是可以试着爆一发,暴力角度得到圆上的点,然后求个距离 ...
- JavaWeb学习----JSTL标签库
一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Co ...
- 第2章 面向对象的设计原则(SOLID):6_开闭原则
6. 开闭原则(Open Closed Principle,OCP) 6.1 定义 (1)一个类应该对扩展开放,对修改关闭.要求通过扩展来实现变化,而且是在不修改己有的代码情况下进行扩展,也不必改动己 ...
- AC日记——津津的储蓄计划 P1089 (水!)
题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里 ...
- QTP学习一添加默认的注释及调用外部vbs文件
一.添加默认注释 1.新建一个TXT文档,将要添加的注释写在文档中 2.再将文档名改为:ActionTemplate.mst 3.将文件放到QTP安装目录(默认为:C:\Program Files\H ...
- Linux下squid代理缓存服务环境部署
代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息. Squid是一个缓存Internet 数据的软件,其接收用户的下载申请,并自动处理所下载的数据.当一个用户想要下载 ...
- iOS请求服务器数据去空NSNull
我们在处理数据库接口的过程中,如果数据中出现null,我们是没法处理的.我在使用NSUserDaults保存后,出现崩溃. null产生原因 null是后台在处理数据的时候,如果没有设置value值, ...
- 修改sqlserver2008默认的数据库文件保存路径
在SSMS(SQL Server Management Studio)中,右键服务器,然后选择属性. 然后数据库设置,再配置数据库默认位置 方法二,直接使用sql语句修改 USE [master] G ...
- form表单和ajax表单提交(Html.BeginForm()、Ajax.BeginForm())的差别
有如下几种区别: 1. Ajax在提交.请求.接收时,都是异步进行的,网页不需要刷新: Form提交则是新建一个页面,哪怕是提交给自己本身的页面,也是需要刷新的: 2. A在提交时,是在后台新建一个请 ...