时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

给定一个字符串S,小Hi希望对S进行K次翻转操作。

每次翻转小Hi会指定两个整数Li和Ri,表示要将S[Li..Ri]进行翻转。(S下标从0开始,即S[0]是第一个字母)

例如对于S="abcdef",翻转S[2..3] 得到S="abdcef";再翻转S[0..5]得到S="fecdba"。

输入

第一行包含一个由小写字母组成的字符串S。

第二行包含一个整数K。

以下K行每行包含两个整数Li和Ri。

对于50%的数据,1 ≤ |S| ≤ 1000

对于100%的数据,1 ≤ |S| ≤ 100000, 1 ≤ K ≤ 100000, 0 ≤ Li ≤ Ri < |S|

输出

输出经过K次翻转后的字符串S

样例输入

abcdef
2
2 3
0 5

样例输出

fecdba

大意:给一个字符串,然后有K个区间翻转操作,求所有操作完成后的字符串。

题解:

splay的经典应用:区间操作(翻转、删除、插入)。

splay备忘:(只是备忘)

首先是rotate操作——不改变树中序遍历。这是splay能够转来转去的基础。relink重新连边的顺序不能变。

然后是splay(x,y)操作——将x旋转到y的子节点位置。注意:两个push_up的位置很重要,不能随意push_up正在向上旋的点。

在splay的过程中分两种情况

(1)x、x->father、x->father->father 在一条线上(x和x->father分别为x->father和x->father->father 的同侧子节点)

这时先rotate(x->father)再rotate(x),虽然rotate()两次,但是x只上升一层(深度减少1),这样做是值得的,因为当三个点在一条线上时,splay有些不平衡,而如此rotate两次后splay变得平衡,这是保证splay不退化的关键操作。

(2)不在一条线上

这就没什么顾虑了,直接将rotate(x)两次就行了,x上升两层。

insert(root,val)——增加新节点时要把它旋转到根节点,这是为了保证splay的平衡性。

各种查找(查找第K大,查找值为val的节点,询问值为val的排名等等)——  二叉查找树基本操作。

区间操作——全部转化为删除排名在[L,R]区间的元素。

将排名L-1的元素旋至根节点,将排名R+1的元素旋至根节点的右子节点。这样,待操作就都在排名R+1的元素的左子树了。

区间操作要像线段树一样把tag   push_down。

下面贴上代码(很多操作不全,懒得写了)

 /*
Welcome Hacking
Wish You High Rating
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
int read(){
int xx=,ff=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')ff=-;ch=getchar();}
while(ch>=''&&ch<=''){xx=(xx<<)+(xx<<)+ch-'';ch=getchar();}
return xx*ff;
}
const int maxn=;
int N,Q;
char str[maxn];
struct SPLAY{
int ch[],v,fa,sum;
bool rev;
void clear()
{ch[]=,ch[]=,v=,fa=,rev=,sum=;}
void init(int pos)
{clear();v=pos;sum=;}
}T[maxn];
int cnt,root;
void push_up(const int&x)
{T[x].sum=T[T[x].ch[]].sum+T[T[x].ch[]].sum+;}
void push_down(const int&x){
if(!T[x].rev)
return;
swap(T[x].ch[],T[x].ch[]);
T[T[x].ch[]].rev^=;
T[T[x].ch[]].rev^=;
T[x].rev=;
}
inline bool which(int x)
{return T[T[x].fa].ch[]==x;}
inline void relink(int x,int y,int tt)
{T[x].ch[tt]=y,T[y].fa=x;}
void rotate(int x){
int y=T[x].fa,ffa=T[y].fa,tt=which(x),ttt=which(y);
relink(ffa,x,ttt);
relink(y,T[x].ch[tt^],tt);
relink(x,y,tt^);
push_up(y);
}
void splay(int x,int tar){
push_down(x);
while(T[x].fa!=tar){
if(T[T[x].fa].fa==tar){
rotate(x);
break;
}
else if(which(x)==which(T[x].fa)){
rotate(T[x].fa);
rotate(x);
}
else{
rotate(x);
rotate(x);
}
}
push_up(x);
if(!tar)
root=x;
}
int build(int L,int R){
if(L>R)
return ;
int mid=(L+R)>>;
int x=++cnt;
if(!root)root=x;
T[x].init(mid);
T[x].ch[]=build(L,mid-);
T[x].ch[]=build(mid+,R);
if(T[x].ch[])
T[T[x].ch[]].fa=x;
if(T[x].ch[])
T[T[x].ch[]].fa=x;
push_up(x);
return x;
}
void trav(int x){
if(!x)
return;
push_down(x);
trav(T[x].ch[]);
if(T[x].v>=&&T[x].v<=N)
printf("%c",str[T[x].v]);
trav(T[x].ch[]);
}
int find_element(int x,int v){
push_down(x);
if(v==T[x].v)
return x;
if(v<T[x].v)
return find_element(T[x].ch[],v);
return find_element(T[x].ch[],v);
}
int find_rank(int x,int rk){
push_down(x);
if(T[T[x].ch[]].sum>=rk)
return find_rank(T[x].ch[],rk);
if(T[T[x].ch[]].sum+==rk)
return x;
return find_rank(T[x].ch[],rk-T[T[x].ch[]].sum-);
}
void rever(int L,int R){
int x=find_rank(root,L),y=find_rank(root,R+);//多插入了边界元素,因此区间有平移
splay(x,);
splay(y,root);
T[T[y].ch[]].rev^=;
}
int get_rank(int x,int v){
if(v==T[x].v)
return ;
if(v<T[x].v)
return get_rank(T[x].L,v);
return get_rank(T[x].R,v)+T[T[x].L].sum+;
}
void ins(int &x,int v){
if(!x){
x=++cnt;
T[x].init(v);
splay(x,);
return;
}
if(v<T[x].v)
insert(T[x].ch[],v);
else
insert(T[x].ch[],v);
}
void del_value(int v){
int temp=get_rank(root,v);
splay(temp-,);
splay(temp+,root);
T[T[temp].ch[]].clear();
T[temp].ch[]=;
}
void del_rank(int L,int R){
int x=find_rank(L),y=find_rank(R+);
splay(x,);
splay(y,root);
T[T[y].ch[]].clear();
T[y].ch[]=;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
gets(str+);
N=strlen(str+);
build(,N+);
Q=read();
while(Q--){
int t1=read()+,t2=read()+;
rever(t1,t2);
}
trav(root);
return ;
}

ins函数有问题

跳过即可


hihocoder 1677 翻转字符串 splay的更多相关文章

  1. [LeetCode] Reverse Vowels of a String 翻转字符串中的元音字母

    Write a function that takes a string as input and reverse only the vowels of a string. Example 1:Giv ...

  2. [LeetCode] Reverse Words in a String 翻转字符串中的单词

    Given an input string, reverse the string word by word. For example, Given s = "the sky is blue ...

  3. [CareerCup] 1.2 Reverse String 翻转字符串

    1.2 Implement a function void reverse(char *str) in C or C++ which reverses a null-terminated string ...

  4. lintcode :Reverse Words in a String 翻转字符串

    题目: 翻转字符串 给定一个字符串,逐个翻转字符串中的每个单词. 样例 给出s = "the sky is blue",返回"blue is sky the" ...

  5. [LeetCode] Reverse Words in a String III 翻转字符串中的单词之三

    Given a string, you need to reverse the order of characters in each word within a sentence while sti ...

  6. [LeetCode] Reverse String II 翻转字符串之二

    Given a string and an integer k, you need to reverse the first k characters for every 2k characters ...

  7. [Swift]LeetCode151. 翻转字符串里的单词 | Reverse Words in a String

    Given an input string, reverse the string word by word. Example: Input: "the sky is blue", ...

  8. C#版(击败100.00%的提交) - Leetcode 151. 翻转字符串里的单词 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  9. LeetCode 151 翻转字符串里的单词

    题目: 给定一个字符串,逐个翻转字符串中的每个单词. 示例 1: 输入: "the sky is blue" 输出: "blue is sky the" 示例 ...

随机推荐

  1. 控制台——args参数的赋值方法

    args参数的赋值方法有好几种,主要介绍两种. 外部传参的方法:先找到bin目录下的exe文件,并创建快捷方法,在目标后面追加参数. 控制台主函数入口实现方法 static void Main(str ...

  2. java攻城狮之路--复习JDBC(PrepareStatement)

    PreparedStatement: 1.可以通过调用 Connection 对象的 preparedStatement() 方法获取 PreparedStatement 对象 2.PreparedS ...

  3. IIS中实现http自动转换到https

    IIS中实现http自动转换到https修改以下文件:C:\WINDOWS\Help\iisHelp\common\403-4.htm 为以下内容<!DOCTYPE HTML PUBLIC &q ...

  4. cordova插件分类

    1.android自动更新功能所需插件 cordova plugin add https://github.com/whiteoctober/cordova-plugin-app-version.gi ...

  5. Spring学习笔记_day01_ioc

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! Spring_day01 spring是一站式的框架, ...

  6. yum进程被占用

    使用yum安装软件的时候出现,/var/run/yum.pid 已被锁定,PID 为 6503 的另一个程序正在运行的问题 [root@localhost mysql]# yum install gc ...

  7. CSS 之自定义滚动条样式

    ::-webkit-scrollbar {/*滚动条整体样式*/ width: 5px; /*高宽分别对应横竖滚动条的尺寸*/ height: 1px; } ::-webkit-scrollbar-t ...

  8. Xilinx FPGA的专用时钟引脚及时钟资源相关

    主要参考了https://www.eefocus.com/liu1teng/blog/12-02/237897_4533d.html .Xilinx UG471.UG472以及Xilinx Forum ...

  9. 6.shell脚本

    6.1 shell基础语法 6.1.1 shell的概述 shell的基本概念 1.什么是shell shell是用户和Linux操作系统之间的接口,它提供了与操作系统之间的通讯方式 shell是一个 ...

  10. oracle的递归运算(树运算) 无限树形

    oracle的递归运算(树运算)start with org_id ='1'connect by prior parent_id=son_id 1.前言   oracle的递归运算,在我们web页面的 ...