HDU_3487

题意:给出n和q,n代表1-n的序列,接下来q有两种操作,Cut a b c:表示把区间[a,b]截掉然后放在第c个数的后面,Flip a b 表示把区间[a,b]反转,经过一系列的q操作,最后输出操作后的序列:

分析:首先建立初始化的树结构之前,先给n设置个极限范围0和n+1,防止特殊情况下越界,如果反转[a,b],则先把第a-1个数放在根节点,把b+1结点的数放在根节点的右儿子下面,此时根节点的右儿子的左儿子为根的子树就是[a,b]区间,然后把反转标记传递给该子树的根节点,如果剪切区间[a,b]则把第c+1个数旋转到根节点处,然后把根节点的右儿子为子树的最左面的节点旋转到该子树的根,此时把剪掉的子树的根节点连到根节点的右儿子的左儿子上面即可,需要注意的是,push_down和push_up的操作

codes:指针

#include"stdio.h"
#include"iostream"
#include"queue"
using namespace std;
struct Link_cut
{ queue<int>q;
struct node //节点结构体
{
int key,val,son,flag;
node *lson,*rson,*fa; //左儿子,右儿子,以及父节点
node()
{
key=val=flag=;
son=;
lson=rson=fa=NULL;
}
};
node *top,*root,*x,*y;
void init() //建立根节点root的父节点top
{
top=new node();
}
int getNum(node *x) //以x为根的子树一共有多少个节点
{
if(x==NULL)return ;
return x->son;
}
void push_up(node *rt)
{
rt->son=getNum(rt->lson)+getNum(rt->rson)+;
}
void push_down(node *rt)
{
if(rt==NULL)return;
if(rt->flag)
{
rt->flag^=;
Reversal(rt);
if(rt->lson!=NULL)
rt->lson->flag^=;
if(rt->rson!=NULL)
rt->rson->flag^=;
}
}
void Rotate(node *x,int k) //k=0左旋k=1右旋
{
node *y=x->fa;
if(k==)
{
y->rson=x->lson;
if(y->rson!=NULL)
y->rson->fa=y; push_up(y);
if(y->fa->rson==y)
y->fa->rson=x;
else
y->fa->lson=x;
x->fa=y->fa; x->lson=y;
y->fa=x;
}
else
{
y->lson=x->rson;
if(y->lson!=NULL)
y->lson->fa=y; push_up(y);
if(y->fa->lson==y)
y->fa->lson=x;
else
y->fa->rson=x;
x->fa=y->fa; x->rson=y;
y->fa=x;
}
}
void Splay(node *x,node *f)//把x旋转到f的下面
{
while(x->fa!=f)
{
node *y=x->fa;
node *z=y->fa;
if(z==f)
{
if(y->rson==x)
Rotate(x,);
else
Rotate(x,);
}
else
{
if(z->rson==y)
{
if(y->rson==x)
{
Rotate(y,);
Rotate(x,);
}
else
{
Rotate(x,);
Rotate(x,);
}
}
else
{
if(y->lson==x)
{
Rotate(y,);
Rotate(x,);
}
else
{
Rotate(x,);
Rotate(x,);
}
}
}
}
if(f==top)
root=x;
}
void RotateTo(node *x,node *f)
{
Splay(x,f);
push_up(x);
}
void RotateTo(int k,node *f)
{
node *x=root;
k++;
while()
{
push_down(x);
int temp=getNum(x->lson)+;
if(k==temp)break;
if(k<temp)
x=x->lson;
else
{
k-=temp;
x=x->rson;
}
}
Splay(x,f);
push_up(x);
}
void creatTree(int l,int r,int k,node *f) //初始化一颗二叉树
{
if(l>r)return;
int mid=(l+r)/;
node *rt=new node();
if(f==top)
root=rt;
if(k==)
{
f->lson=rt;
rt->fa=f;
rt->key=mid;
}
else
{
f->rson=rt;
rt->fa=f;
rt->key=mid;
}
creatTree(l,mid-,,rt);
creatTree(mid+,r,,rt);
push_up(rt);
}
void Reversal(node *x)//交换x左右儿子的结点
{
if(x==NULL)return;
node *y=x->lson;
x->lson=x->rson;
x->rson=y;
}
node *Find(int k) //找到第k的结点
{
node *x=root;
k++;
while()
{
push_down(x);
int temp=getNum(x->lson)+;
if(k==temp)break;
else if(k<temp)
x=x->lson;
else
{
k-=temp;
x=x->rson;
}
}
return x;
}
node *FindRight(node *rt) //找到以rt为根节点的最右一个结点
{
node *x=rt;
while()
{
push_down(x);
if(x->rson==NULL)
break;
x=x->rson;
}
return x;
}
node *FindLeft(node *rt) //找到以rt为根节点的最左一个结点
{
node *x=rt;
while()
{
push_down(x);
if(x->lson==NULL)break;
x=x->lson;
}
return x;
}
void Link(node *rt,int k) //把rt为根的子树连接到第k个结点的后面
{
root->rson->lson=NULL; //把区间砍掉
node *x=Find(k);
RotateTo(x,top);
node *y=FindLeft(root->rson);
RotateTo(y,root); root->rson->lson=rt;
rt->fa=root->rson;
}
void Output(node *x,int n)
{
if(x==NULL)return;
push_down(x);
Output(x->lson,n);
if(x->key>=&&x->key<=n)
q.push(x->key);
Output(x->rson,n);
}
}h;
int main()
{
int n,q;
while(scanf("%d%d",&n,&q)!=-)
{
if(n==-&&q==-)break;
h.init();
h.creatTree(,n+,,h.top);
char op[];
int a,b,c; while(q--)
{ scanf("%s%d%d",op,&a,&b);
if(op[]=='C')
{
scanf("%d",&c);
h.RotateTo(a-,h.top);
h.RotateTo(b+,h.root);
h.Link(h.root->rson->lson,c);
}
else
{
h.RotateTo(a-,h.top);
h.RotateTo(b+,h.root);
h.root->rson->lson->flag^=;
}
}
while(!h.q.empty())
{
h.q.pop();
}
h.Output(h.root,n);
printf("%d",h.q.front());
h.q.pop();
while(!h.q.empty())
{
printf(" %d",h.q.front());
h.q.pop();
}
puts(""); }
}
/*
8 1
CUT 3 5 4 5 1
CUT 2 3 1 8 3
Cut 3 6 3
Cut 2 6 2
Cut 3 6 4 8 1
Flip 2 6 10 5
Cut 2 6 3
Flip 4 9
Flip 5 8
Cut 6 7 3
Flip 4 5
*/

codes:数组模拟

#include"stdio.h"
#include"iostream"
#include"queue"
#include"string.h"
#define M 3000005
using namespace std; struct Text
{
int son[M][],fa[M],flip[M],num[M];
int top;
int root;
vector<int>p;
void init(int n)
{
top=n+;
for(int i=;i<=n+;i++)
{
num[i]=;
flip[i]=;
son[i][]=son[i][]=-;
fa[i]=-;
}
}
void Rotate(int x,int k)
{
int y=fa[x];
if(k==)
{
son[y][]=son[x][];
if(son[y][]!=-)
fa[son[y][]]=y; push_up(y);
if(son[fa[y]][]==y)
son[fa[y]][]=x;
else
son[fa[y]][]=x;
fa[x]=fa[y]; son[x][]=y;
fa[y]=x;
}
else
{
son[y][]=son[x][];
if(son[y][]!=-)
fa[son[y][]]=y; push_up(y);
if(son[fa[y]][]==y)
son[fa[y]][]=x;
else
son[fa[y]][]=x;
fa[x]=fa[y]; son[x][]=y;
fa[y]=x;
}
}
int Find(int k)
{
k++;
int x=root;
while()
{
push_down(x);
int temp=getNum(son[x][])+;
if(temp==k)break;
else if(k<temp)
x=son[x][];
else
{
k-=temp;
x=son[x][];
}
}
return x;
}
void splay(int x,int f)
{
if(x==-)return;
while(fa[x]!=f)
{
int y=fa[x];
int z=fa[y];
if(z==f)
{
if(son[y][]==x)
Rotate(x,);
else
Rotate(x,);
}
else
{
if(son[z][]==y)
{
if(son[y][]==x)
{
Rotate(y,);
Rotate(x,);
}
else
{
Rotate(x,);
Rotate(x,);
}
}
else
{
if(son[y][]==x)
{
Rotate(y,);
Rotate(x,);
}
else
{
Rotate(x,);
Rotate(x,);
}
}
}
}
if(f==top)
root=x;
}
void RotateTo(int x,int f,int type)
{
if(!type)
x=Find(x);
splay(x,f);
push_up(x);
}
void Reversal(int x)
{
if(x==-)return;
int y=son[x][];
son[x][]=son[x][];
son[x][]=y;
}
void creat(int l,int r,int k,int f)
{
if(l>r)return;
int mid=(l+r)/;
if(f==top)
root=mid;
son[f][k]=mid;
fa[mid]=f;
creat(l,mid-,,mid);
creat(mid+,r,,mid);
push_up(mid);
}
int getNum(int x)
{
if(x==-)return ;
return num[x];
}
void push_up(int rt)
{
num[rt]=getNum(son[rt][])+getNum(son[rt][])+;
}
void push_down(int rt)
{
if(rt==-)return;
if(flip[rt])
{
flip[rt]^=;
Reversal(rt);
if(son[rt][]!=-)
flip[son[rt][]]^=;
if(son[rt][]!=-)
flip[son[rt][]]^=;
}
}
int findLeft(int rt)
{
int x=rt;
while()
{
push_down(x);
if(son[x][]==-)break;
x=son[x][];
}
return x;
}
void CUT(int a,int b,int c)
{
RotateTo(a-,top,);
RotateTo(b+,root,);
int rt=son[son[root][]][];
son[son[root][]][]=-; RotateTo(c,top,);
int x=findLeft(son[root][]);
RotateTo(x,root,);
son[son[root][]][]=rt;
fa[rt]=son[root][];
}
void FLIP(int a,int b)
{
RotateTo(a-,top,);
RotateTo(b+,root,);
int x=son[son[root][]][];
flip[x]^=;
}
void dfs(int rt,int n)
{
if(rt==-)return;
push_down(rt);
dfs(son[rt][],n);
if(rt>=&&rt<=n)
p.push_back(rt);
dfs(son[rt][],n); }
void Output(int n)
{
dfs(root,n);
printf("%d",p[]);
for(int i=;i<(int)p.size();i++)
printf(" %d",p[i]);
puts("");
p.clear();
}
}text;
int main()
{
int n,q;
while(scanf("%d%d",&n,&q)!=-)
{
if(n==q&&n==-)break;
text.init(n);
text.creat(,n+,,text.top);
int a,b,c;
char op[]; while(q--)
{
scanf("%s%d%d",op,&a,&b);
if(op[]=='C')
{
scanf("%d",&c);
text.CUT(a,b,c);
}
else
text.FLIP(a,b); }
text.Output(n); }
return ;
} /*
10 5
Cut 2 6 3
Flip 4 9
Flip 5 8
Cut 6 7 3
Flip 4 5 10 5
Flip 4 9
Flip 5 8
Cut 6 7 3
Flip 4 5 10 1
Flip 2 9
*/
 

Hdu-3487 Splay树,删除,添加,Lazy延迟标记操作的更多相关文章

  1. hdu 3436 splay树+离散化*

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  2. HDU 3487 Splay

    给定两种操作,一种是把一个数列的某一段切下来插到剩余数列的某一个位置上. 一种是翻转操作,把数列的某一段进行翻转. 都是Splay的基本操作.标准的Rotateto调整出 [a,b]区间.然后对[a, ...

  3. 题解报告:hdu 1698 Just a Hook(线段树区间修改+lazy懒标记的运用)

    Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for m ...

  4. hdu 1890 splay树

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tot ...

  5. HDU 4391 Paint The Wall(分块+延迟标记)

    Paint The Wall Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. 题解报告:poj 3468 A Simple Problem with Integers(线段树区间修改+lazy懒标记or树状数组)

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  7. [线段树系列] LCT打延迟标记的正确姿势

    这一篇博客将教你什么? 如何用LCT打延迟标记,LCT和线段树延迟标记间的关系,为什么延迟标记要这样打. ——正片开始—— 学习这一篇博客前,确保你会以下知识: Link-Cut-Tree,普通线段树 ...

  8. Chip Factory HDU - 5536 字典树(删除节点|增加节点)

    题意: t组样例,对于每一组样例第一行输入一个n,下面在输入n个数 你需要从这n个数里面找出来三个数(设为x,y,z),找出来(x+y)^z(同样也可以(y+z)^1)的最大值 ("^&qu ...

  9. HDU 3487 Splay tree

    Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

随机推荐

  1. sql_action

    CREATE TABLE w SELECT * FROM existing_table 2 日期x idm valuexm 日期x idn  valuexn 日期y idm  valueym 日期y ...

  2. Kafka可靠性的思考

    首先kafka的throughput 很牛逼,参考:http://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million- ...

  3. ArcGIS for Sever 10.1 服务迁移与恢复

    === 声明:以下内容本是自己写给单位内部同事的参考手册,但是被传到百度文库中.陆续有用户就这方面的问题,通过电话,邮件等方式联系我.首先,感到荣幸.其次是,由于本人当时测试和编写的时候,由于仓促,可 ...

  4. android文字阴影效果(转)

    关于android文字阴影,共有四个属性可以设置: android:shadowColor :阴影颜色 android:shadowDx :阴影x方向位移 android:shadowDy :阴影y方 ...

  5. (IOS)Swift Music 程序分析

    本文主要分享下楼主在学习Swift编程过程中,对GitHub上的一个开源App Swift Music的研究心得. 项目地址:https://github.com/xujiyao123/SwiftMu ...

  6. 用户登录验证例题用的ajax

    1.登录页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...

  7. BLE-NRF51822教程18-overview

    转自:http://blog.csdn.NET/xgbing 蓝牙协议栈 nrf51822开发中,蓝牙协议栈和应用开发是分开的. (1)兼容蓝牙4.0低功耗协议栈基带层,L2CAP\AAT\SM\GA ...

  8. python环境搭建

    Python下载 Python最新源码,二进制文档,新闻资讯等可以在Python的官网查看到: Python官网:http://www.python.org/ 你可以在一下链接中下载Python的文档 ...

  9. javax.management.NotCompliantMBeanException

    public interface QueueMBean { } 假如接口名叫 XMBean ,那么实现名就必须一定是X,而且是大小写敏感的. public class Queue implements ...

  10. BAT for循环

    一,数字循环 echo off & color 0A for /l %%i in (1,1,10) do ( echo %%i ) pause > nul 输出: 1 2 3 4 5 6 ...