时间限制: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. Angular——自定义指令

    基本介绍 有了很多内置指令,但是依然无法满足我们的需要,我们可以自己定义一个指令,实现默写功能. 基本使用 directive方法可以帮助我们自己定义一个指令,它的返回方式一共有四种,ECMA,代表所 ...

  2. JS——事件基础应用

    直接写在html标签里: <h1 onclick="this.innerHTML='谢谢!'">请点击该文本</h1> 另外一种在脚本里调用: <!D ...

  3. 救济金发放(The Dole Queue, UVa 133)

    n(n<20)个人站成一圈,逆时针编号为1-n.有两个官员,A从1开始逆时针数,B从n开 始顺时针数.在每一轮中,官员A数k个就停下来,官员B数m个就停下来(注意有可能两个 官员停在同一个人上) ...

  4. 7-11 社交网络图中结点的“重要性”计算 (30 分)(Dijkstra算法)

    题意:  思路:对每个输入的点跑一遍dijkstra算法,然后对这个点到所有点的距离求和按公式输出就可以了. (这次尝试了用数组模拟链表来做最短路问题,刷新了自己对最短路的理解) 这里构造链表的过程我 ...

  5. 逆元Inv(模板+应用)

    逆元: 如果满足公式,则有a 是 b的逆元同时b也是a的逆元. 逆元的应用: 设c为b在对m取余的意义下的逆元: 在求解公式 (a / b) % m的时候,如果b可能会非常的大,所以会出现爆精度的问题 ...

  6. [luogu2594 ZJOI2009]染色游戏(博弈论)

    传送门 Solution 对于硬币问题,结论是:当前局面的SG值等于所有背面朝上的单个硬币SG值的异或和 对于求单个背面朝上的硬币SG值...打表找规律吧 Code //By Menteur_Hxy ...

  7. yum更换国内源及yum下载rpm包

    一.yum更换国内源 运维开发技术交流群欢迎大家加入一起学习(QQ:722381733) 1.前往yum文件路径地址 [root@web1 ~]# cd /etc/yum.repos.d/ [root ...

  8. C#学习笔记_14_接口&命名空间

    14_接口&命名空间 接口 一系列规范 语法: 如果一个类的后面既有父类也有接口,那么一定是父类在前,接口靠后 一个类可以实现多个接口 规范:接口命名以大写字母 I 开头 接口中可以包含接口方 ...

  9. https://github.com/MediaTek-Labs/linkit-smart-7688-feed编译失败

    mkdir -p /home/fly/workdir/LinkltSmart7688Duo-20170626/openwrt/dl/home/fly/workdir/LinkltSmart7688Du ...

  10. 3D全景之ThreeJs

    3D全景之ThreeJs 一.前言 随着H5越来越多的被应用到各个领域,3D也越来越频繁的出现在各个H5案例中,今天我们就来讨论一下3D全景的实现. 据百度百科上介绍:720全景是视角超过人的正常视角 ...