时间限制: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. js indexOf 列表筛选

    先来一堆效果图:  代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  2. Less——less基本安装

    1.下载node.js 我们需要NodeJ运行LESS示例. 要下载NodeJ,请打开链接https://nodejs.org/en/ 2.node.js安装是否正确 在cmd中输入lessc -v, ...

  3. 9-4前端vue面试的问题

    就没有什么顺序了,肖师傅的一些提问: 1- 配置文件中proxyTable的作用 2-@import '~styles/mixins.styl'  ~的作用 3-vue模拟的本地中访问地址的url带有 ...

  4. rrdtool 实践

    rrdtool 实践 rrdtool 参数比较多,如果直接看文档,不知从何入手,直接从例子入手这样容易理解,模拟网卡流量 1. 创建数据库 rrdtool create Flow.rrd --star ...

  5. c#中动态创建textbox并且从数据库中获取表中数据添加到textbox中

    private void FormLugOther_Load(object sender, EventArgs e) { foreach (string str in FormLug.FieldLis ...

  6. nexus3.x启动不起来

    1.首先说两种启动命令,网上最多的是用./nexus start.这种是后台启动,看不到实时日志:./nexus run 是实时启动可以看到日志. 2.linux下解压nexus-3.6.2-01-u ...

  7. Secret of Chocolate Poles (Aizu1378——dp)

    Select Of Chocolate Poles 题意:有一个竖直放置的高度为l cm的盒子,现在有三种方块分别为1cm的白块,1cm的黑块,k cm的黑块,要求第一块放进去的必须是黑色的,盒子最上 ...

  8. 爬虫文件存储-2:MongoDB

    1.连接MongoDB 连接 MongoDB 我们需要使用 PyMongo 库里面的 MongoClient,一般来说传入 MongoDB 的 IP 及端口即可,第一个参数为地址 host,第二个参数 ...

  9. JDK,JRE,JVM三者关系

    已上图,如有疏漏错误请在下面评论区指出,感激不尽!

  10. hdu2000 ASCII码排序【C++】

    ASCII码排序 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...