hihocoder 1677 翻转字符串 splay
描述
给定一个字符串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的更多相关文章
- [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 ...
- [LeetCode] Reverse Words in a String 翻转字符串中的单词
Given an input string, reverse the string word by word. For example, Given s = "the sky is blue ...
- [CareerCup] 1.2 Reverse String 翻转字符串
1.2 Implement a function void reverse(char *str) in C or C++ which reverses a null-terminated string ...
- lintcode :Reverse Words in a String 翻转字符串
题目: 翻转字符串 给定一个字符串,逐个翻转字符串中的每个单词. 样例 给出s = "the sky is blue",返回"blue is sky the" ...
- [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 ...
- [LeetCode] Reverse String II 翻转字符串之二
Given a string and an integer k, you need to reverse the first k characters for every 2k characters ...
- [Swift]LeetCode151. 翻转字符串里的单词 | Reverse Words in a String
Given an input string, reverse the string word by word. Example: Input: "the sky is blue", ...
- C#版(击败100.00%的提交) - Leetcode 151. 翻转字符串里的单词 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
- LeetCode 151 翻转字符串里的单词
题目: 给定一个字符串,逐个翻转字符串中的每个单词. 示例 1: 输入: "the sky is blue" 输出: "blue is sky the" 示例 ...
随机推荐
- Miller Rabin 大素数测试
PS:本人第一次写随笔,写的不好请见谅. 接触MillerRabin算法大概是一年前,看到这个算法首先得为它的神奇之处大为赞叹,竟然可以通过几次随机数据的猜测就能判断出这数是否是素数,虽然说是有误差率 ...
- 吐得了,vue的多选组合框回显必须是字符串集合
下面这个typeIdList,如果给他赋值,就能回显到页面,但是必须是字符串的集合,如果是数值类型的id,不好意思,请转成字符串
- Java中面向对象三大特性之——多态
多态的概述: 多态是继封装.继承之后,面向对象的第三大特性. 生活中,比如跑的动作,小猫.小狗和大象,跑起来是不一样的.再比如飞的动作,昆虫.鸟类和飞机,飞起来也是不一样的.可见,同一行为,通过不同 ...
- 通过JS唤醒app(安卓+ios)
有需求说要通过页面按钮唤醒app,或者手机上没有这款app跳转到商店,然后刚开始也是查了资料的,结果发现一头雾水,不过最后还是捣鼓出来了,当然也参考了前人分享的经验,下面我就将方法整理一下: 首先明确 ...
- 《零压力学Python》 之 第一章知识点归纳
第一章(初识Python)知识点归纳 Python是从ABC语言衍生而来的 ABC语言是Guido参与设计的一种教学语言,为非专业编程人员所开发的. Python是荷兰程序员 Guido Van Ro ...
- 使用Autofac 依赖注入及 swagger 之startup配置
言语有限,代码如下: public IServiceProvider ConfigureServices(IServiceCollection services) { services .AddCor ...
- 手写DAO框架(二)-开发前的最后准备
-------前篇:手写DAO框架(一)-从“1”开始 --------- 前言:前篇主要介绍了写此框架的动机,把主要功能点大致介绍了一下.此篇文章主要介绍开发前最后的一些准备.主要包括一些基础知识点 ...
- Java基础——基础数据类型与读入输出
首先我们写完了HelloWorld就学会了java的一种输出 System.out.println() 用起来就像是被强化过的C++的puts函数 或者就是自带endl的cout函数,中间的" ...
- Git学习总结(3)——代码托管平台简介
可以说GitHub的出现完全颠覆了以往大家对代码托管网站的认识.GitHub不但是一个代码托管网站,更是一个程序员的SNS社区.GitHub真正迷人的是它的创新能力与Geek精神,这些都是无法模仿的. ...
- FOJ2250 不可能弹幕结界
Problem 2250 不可能弹幕结界 Time Limit: 1000 mSec Memory Limit : 65536 KB Problem Description 咲夜需要穿过一片弹幕 ...