HDU3487 play with chain
题目大意:给出1到n的有序数列,现在有两个操作:
1.CUT a b c 把第a到第b个数剪切下来,放到剩下的第c个数的后边。
2.FLIP a b 把第a到第b个数反转。
经过总共m次操作后,求现在的数列。
n,m<300000
分析:典型的splay题。包含的操作即:查找第k大,剪切,插入,反转等操作。
维护size,rev(反转标记)即可。
通过size可以找到第k大,通过rev做懒标记,可以进行反转。
具体说就是,比如要剪切CUT a,b,c,以先把第a-1个节点splay到根的位置,然后把第b+1个节点spaly到根的右儿子的位置,则a到b这一段就刚好是根的右儿子的左子树了,然后把它剪切下来。再把第c节点splay到根的位置,把第c+1个节点splay到根的右儿子的位置,再把刚才剪切的那一段接在根的右儿子的左儿子位置即可。FLIP a b的话,先把第a-1个节点splay到根的位置,把第b+1个节点splay到根的右儿子的位置,然后对根的右儿子的左子树打上懒标记即可。注意:打蓝标记应该是tree[i].rev^=1,而不是tree[i].rev=1。我就是这样wa了一次。
因为splay树的伸展特性,splay树中要增加两个额外的虚拟节点,即头节点和尾节点。初始时把头结点作为根节点,把尾节点作为根的右儿子。有效节点作为根的左儿子的右子树。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- using namespace std;
- #define MAXN 300505
- int tot,root,n,m,a,b,c;
- char str[];
- struct node
- {
- int val,fa,sz;
- bool rev;
- int ch[];
- }tree[MAXN];
- void newnode(int &r,int father,int val)
- {
- tot++;
- r=tot;
- tree[tot].fa=father;
- tree[tot].val=val;
- }
- void build(int &root,int l,int r,int father)
- {
- if(l>r)return;
- int mid=(l+r)/;
- newnode(root,father,mid);
- build(tree[root].ch[],l,mid-,root);
- build(tree[root].ch[],mid+,r,root);
- tree[root].sz=tree[tree[root].ch[]].sz+tree[tree[root].ch[]].sz+;
- }
- void init()
- {
- tot=root=;
- memset(tree,,sizeof tree);
- newnode(root,,-);
- newnode(tree[root].ch[],root,-);
- build(tree[tree[].ch[]].ch[],,n,tree[].ch[]);
- tree[tree[].ch[]].sz=tree[tree[tree[].ch[]].ch[]].sz+;
- tree[].sz=tree[tree[].ch[]].sz+;
- }
- void pd(int &r)
- {
- if(tree[r].rev==)
- {swap(tree[r].ch[],tree[r].ch[]);
- tree[tree[r].ch[]].rev^=;
- tree[tree[r].ch[]].rev^=;
- tree[r].rev=;
- }
- }
- void pu(int &r)
- {
- tree[r].sz=tree[tree[r].ch[]].sz+tree[tree[r].ch[]].sz+;
- }
- void rotato(int &r,bool kind)
- {
- int y=tree[r].fa;
- int yy=tree[y].fa;
- if(yy)
- {
- tree[yy].ch[tree[yy].ch[]==y]=r;
- }
- tree[r].fa=yy;
- tree[tree[r].ch[kind]].fa=y;
- tree[y].ch[!kind]=tree[r].ch[kind];
- tree[y].fa=r;
- tree[r].ch[kind]=y;
- pu(y);
- pu(r);
- }
- void splay(int &r,int goal)
- {
- while(tree[r].fa!=goal)
- {
- int y=tree[r].fa;
- int yy=tree[y].fa;
- if(yy==goal)rotato(r,tree[y].ch[]==r);
- else
- {
- int kind=(tree[y].ch[]==r);
- if(tree[yy].ch[kind]==y)
- {
- rotato(r,kind);
- rotato(r,!kind);
- }
- else
- {
- rotato(y,kind);
- rotato(r,kind);
- }
- }
- }
- if(goal==)
- root=r;
- }
- int find(int r,int k)
- {
- pd(r);
- if(tree[tree[r].ch[]].sz==k-)
- return r;
- else if(tree[tree[r].ch[]].sz>k-)
- return find(tree[r].ch[],k);
- else return find(tree[r].ch[],k-tree[tree[r].ch[]].sz-);
- }
- void print(int &r)
- {
- pd(r);
- if(tree[r].ch[])
- print(tree[r].ch[]);
- if(tree[r].val!=-){printf("%d",tree[r].val);if(tot>)printf(" ");tot--;}
- if(tree[r].ch[])
- print(tree[r].ch[]);
- }
- int main()
- {
- while(scanf("%d%d",&n,&m)&&(n>=&&m>=))
- {
- init();
- for(int i=;i<m;i++)
- {
- scanf("%s",str);
- if(str[]=='C')
- {
- scanf("%d%d%d",&a,&b,&c);
- int x1=find(root,a);
- int y1=find(root,b+);
- splay(x1,);
- splay(y1,root);
- int t=tree[tree[root].ch[]].ch[];
- tree[tree[root].ch[]].ch[]=;
- pu(tree[root].ch[]);
- pu(root);
- x1=find(root,c+);
- y1=find(root,c+);
- splay(x1,);
- splay(y1,root);
- tree[tree[root].ch[]].ch[]=t;
- tree[t].fa=tree[root].ch[];
- pu(tree[root].ch[]);
- pu(root);
- }
- else
- {
- scanf("%d%d",&a,&b);
- int x=find(root,a);
- int y=find(root,b+);
- splay(x,);
- splay(y,root);
- tree[tree[tree[root].ch[]].ch[]].rev^=;
- }
- }
- print(root);
- printf("\n");
- }
- }
HDU3487 play with chain的更多相关文章
- HDU--3487 Play with Chain (Splay伸展树)
Play with Chain Problem Description YaoYao is fond of playing his chains. He has a chain containing ...
- HDU3487 Play With Chain [Splay]
题目传送门 题目描述 Problem Description YaoYao is fond of playing his chains. He has a chain containing n dia ...
- HDU3487 Play with Chain splay 区间反转
HDU3487 splay最核心的功能是将平衡树中的节点旋转到他的某个祖先的位置,并且维持平衡树的性质不变. 两个操作(数组实现) cut l,r, c把[l,r]剪下来放到剩下序列中第c个后面的位置 ...
- HDU-3487 Play with Chain Splay tee区间反转,移动
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 对于一个数列有两种操作:1.CUT a b c,先取出a-b区间的数,然后把它们放在取出后的第c ...
- 【HDU3487】【splay分裂合并】Play with Chain
Problem Description YaoYao is fond of playing his chains. He has a chain containing n diamonds on it ...
- HDU 3487 Play with Chain | Splay
Play with Chain Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- hdu3487 splay树
Play with Chain Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- HDU 3487 Play with Chain (splay tree)
Play with Chain Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- STM32用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain现象和解决方案
现象 CPU: STM32107VC 用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain 如图无法查找到硬件就是CPU 提示1:NO Cortex ...
随机推荐
- 51nod 1135 原根
题目链接:51nod 1135 原根 设 m 是正整数,a是整数,若a模m的阶等于φ(m),则称 a 为 模m的一个原根.(其中φ(m)表示m的欧拉函数) 阶:gcd(a,m)=1,使得成立的最小的 ...
- MVC5 + EF6 入门完整教程一:从0开始
第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定". 直接讲这些 "约定" 会让人困惑,而且东西太多容易忘记 ...
- 安装Pod时提示ERROR: While executing gem ... (Errno::EPERM) Operation not permitted - /usr/bin/pod
环境:OSX EI 10.11.1 昨天切换gem源后,招待pod安装没有任何问题,也可以正常用$ gem sources --add https://ruby.taobao.org/ --remov ...
- iOS开发拓展篇—音频处理(音乐播放器5)
iOS开发拓展篇—音频处理(音乐播放器5) 实现效果: 一.半透明滑块的设置 /** *拖动滑块 */ - (IBAction)panSlider:(UIPanGestureRecognizer *) ...
- codeforces 451E Devu and Flowers
题意:有n个瓶子每个瓶子有 f[i] 支相同的颜色的花(不同瓶子颜色不同,相同瓶子花视为相同) 问要取出s支花有多少种不同方案. 思路: 如果每个瓶子的花有无穷多.那么这个问题可以转化为 s支花分到 ...
- sscanf函数
sscanf函数用法举例 #include <stdio.h> #include <string.h> #define N 512 int main() { char buf[ ...
- Documentum常见问题11-xplore全文检索时找不到相关内容
最近帮助同事处理了一个关于全文检索的问题,随手记录下来供以后参考. 问题一 某些Cabinet下的文件可以全文检索到,但某些Cabinet下的数据全文检索不成功. 新建了一个Docbase-AADCT ...
- 使用rpm命令卸载程序
步骤1.rpm -qa|grep 程序名称 步骤2.rpm -e 安装包名称 --nodeps
- 在mahout安装目录下输入mahout 提示 ERROR: Could not find mahout-examples-*.job
错误:ERROR: Could not find mahout-examples-*.job in /home/grid/mahout-distribution-0.8 or /home/grid/m ...
- php 判断复选框checkbox是否被选中
php 判断复选框checkbox是否被选中 复选框checkbox在php表单提交中经常被使用到,本文章通过实例向大家介绍php如何判断复选框checkbox中的值是否被选中,需要的朋友可以参考 ...