描述

给定一个字符串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

比赛的时候以为可以用lazy下压标记,但是后面lazy失去了作用。这道题不能用线段树做的原因不是因为数据范围,而是这道题涉及到了翻转操作,线段树不支持这种操作,所以用splay来维护。

现在模板初步成型。

对于初始值:

  • 如果是插入和查询一起操作,那就按顺序来。
  • 否则,初始时,二分建树。不然一个一个加,会成一条链,然后N^2爆炸。

对于区间:

  • 可能是有id的,对id在[L,R]之间进行操作,则查找L的前一个点,和R的后一个点,然后操作。(即find函数)
  • 也可能没有id,对当前队伍的从前往后的第[L,R]th之间进行操作,则先查找第L大...。(即findkth函数)
  • 如果存在反转rev操作,也只能用查找第k大来得到区间(上面第二种)。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=;
const int inf=;
char c[maxn];int n;
struct SplayTree
{
int ch[maxn][],fa[maxn],rev[maxn],sz[maxn];
int cnt,root;
void init()
{
cnt=; root=(+n+)>>;
}
void build(int L,int R,int pre)
{
if(L>R) return ;//build不同于线段树,这里有可能大于。
if(L==R) {
fa[L]=pre;sz[L]=;
ch[pre][L>=pre]=L;
return ;
}int Mid=(L+R)>>;
build(L,Mid-,Mid);build(Mid+,R,Mid);//这里好像有点乱
fa[Mid]=pre; pushup(Mid);
ch[pre][Mid>=pre]=Mid;
}
void pushup(int x)
{
sz[x]=;
if(ch[x][]) sz[x]+=sz[ch[x][]];
if(ch[x][]) sz[x]+=sz[ch[x][]];
}
void pushdown(int x)
{
if(!rev[x]) return ;
swap(ch[x][],ch[x][]);
rev[ch[x][]]^=;rev[ch[x][]]^=;
rev[x]=;
}
int find(int x,int rk)//ok
{
pushdown(x);//莫忘
if(sz[ch[x][]]==rk-) return x;
if(sz[ch[x][]]>=rk) return (find(ch[x][],rk));
return find(ch[x][],rk-sz[ch[x][]]-);
}
void rotate(int x,int opt)//ok
{
int y=fa[x],z=fa[y];
pushdown(y);pushdown(x);
if(z!=) ch[z][ch[z][]==y]=x;fa[x]=z;
ch[y][opt]=ch[x][opt^];fa[ch[x][opt^]]=y;
ch[x][opt^]=y;fa[y]=x;
pushup(y);
}
void splay(int x,int y)//把x移到y下面
{
pushdown(x);
while(fa[x]!=y){
int f=fa[x],ff=fa[f];
int c1=(ch[f][]==x),c2=(ch[ff][]==f);//记录c1 c2,因为rotate之后儿子关系会改变。
if(ff==y) rotate(x,c1);
else {
if(c1^c2) rotate(x,c1),rotate(x,c2);
else rotate(f,c2),rotate(x,c1);
}
} pushup(x); if(!y) root=x;//提到root
}
void revers(int L,int R)
{
int x=find(root,L-),y=find(root,R+);
splay(x,); splay(y,x);
rev[ch[y][]]^=;
}
void print(int x)
{
pushdown(x);
if(ch[x][]) print(ch[x][]);
if(x>=&&x<=n+) printf("%c",c[x]);
if(ch[x][]) print(ch[x][]);
}
}Tree;
int main()
{
int i,m,L,R;scanf("%s",c+);
n=strlen(c+);Tree.init();//莫忘了初始root
Tree.build(,n+,); scanf("%d",&m);
for(i=;i<=m;i++){
scanf("%d%d",&L,&R);
Tree.revers(L+,R+);
} Tree.print(Tree.root);
return ;
}

HihoCoder1677 : 翻转字符串(Splay)(区间翻转)的更多相关文章

  1. hihocoder 1677 翻转字符串 splay

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个字符串S,小Hi希望对S进行K次翻转操作. 每次翻转小Hi会指定两个整数Li和Ri,表示要将S[Li..Ri]进行 ...

  2. hdu-1890-Robotic Sort splay区间翻转

    题意: 依次找第i大的数下标pos[i],然后将区间[i,pos[i]]翻转 分析: splay树区间翻转 // File Name: ACM/HDU/1890.cpp // Author: Zlbi ...

  3. bzoj 3223 文艺平衡树 splay 区间翻转

    Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 17715  Solved: 7769[Submit][Status][ ...

  4. bzoj 1251序列终结者 splay 区间翻转,最值,区间更新

    序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 4594  Solved: 1939[Submit][Status][Discuss] De ...

  5. BZOJ 3223 Splay区间翻转

    思路: 区间翻转的裸题 终于tm理解splay了-- //By SiriusRen #include <cstdio> #include <cstring> #include ...

  6. splay区间翻转

    原题P3391 [模板]文艺平衡树(Splay) 题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: ...

  7. hdu1890 Robotic Sort (splay+区间翻转单点更新)

    Problem Description Somewhere deep in the Czech Technical University buildings, there are laboratori ...

  8. 2019牛客国庆集训派对day1 K题 双向链表练习题 splay区间翻转

    题目链接: 解法: 先建n颗平衡树,合并的时候将a中最右的结点翻转到根节点,b中最左的结点翻转到根节点,对合并后的根节点进行标记. #include <bits/stdc++.h> usi ...

  9. Splay(区间翻转)&树套树(Splay+线段树,90分)

    study from: https://tiger0132.blog.luogu.org/slay-notes P3369 [模板]普通平衡树 #include <cstdio> #inc ...

  10. hdu 1890 Robotic Sort(splay 区间反转+删点)

    题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...

随机推荐

  1. Scrapy教程

    Scrapy教程 原文地址https://doc.scrapy.org/en/latest/intro/tutorial.html 此教程我们假设你已经装好了Scrapy,如果没有请查看安装指南.. ...

  2. elementary OS安装搜狗输入法

    © 版权声明:本文为博主原创文章,转载请注明出处 1.添加搜狗输入法的软件源 sudo add-apt-repository ppa:fcitx-team/nightly 1.1 可能遇到的问题: s ...

  3. Visual Studio 连接 SQL Server 的connectionStringz和

    近期C#和数据结构的课程设计多次用到了C#中连接SQL Server数据库的问题,当中涉及到数据库文件的附加和连接问题. 当中最烦人的就是  SqlConnection(String connStr) ...

  4. SQL Server中排名函数row_number,rank,dense_rank,ntile详解

    SQL Server中排名函数row_number,rank,dense_rank,ntile详解 从SQL SERVER2005开始,SQL SERVER新增了四个排名函数,分别如下:1.row_n ...

  5. Java8中 Date和LocalDateTime的相互转换

    一.在Java 8中将Date转换为LocalDateTime 方法1: 将Date转换为LocalDatetime,我们可以使用以下方法: 1.从日期获取ZonedDateTime并使用其方法toL ...

  6. 关于 Swift 的一点初步看法

    本文转自:http://onevcat.com/2014/06/my-opinion-about-swift/ 感谢原作者 尽管四点半就起床去排队等入场,结果还是仅仅能坐在了蛮后面的位置看着大屏幕參加 ...

  7. mongo 介绍

    [介绍]:MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能.MongoDB 旨在为WEB应用提供可扩展的高性能数据存 ...

  8. MVC教程--MiniProfiler.EF监控调试MVC和EF的性能

    上一篇谈到mvc中ef输出执行sql日志:来谈用mvc开发项目的调试和性能监控.EF框架自动给我生成sql语句,当我们的程序遇到性能问题的时候我们可以用MiniProfiler.EF来监控调试MVC和 ...

  9. BCH分叉是一次站队博弈

    BCH分叉在即,很多人说BCH本次分叉实质是大佬间的斗争,主要是本次BCH分叉主要分为两大派别: 一派以BCH用户量最大的客户端Bitcoin ABC开发组为主,要在11月15日展开硬分叉升级,主要升 ...

  10. git版本控制-- Windows+Git+TortoiseGit+COPSSH安装图文教程

    Windows+Git+TortoiseGit+COPSSH 安装图文教程 教程网址: http://www.liaoxuefeng.com/wiki/0013739516305929606dd183 ...