描述

给定一个字符串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. Codeforces 223C Partial Sums 数论+组合数学

    题意非常easy,求不是那么好求的,k非常大 要操作非常多次,所以不可能直接来的.印象中解决操作比較多无非线段树 循环节 矩阵 组合数等等吧,这道题目 也就仅仅能多画画什么 的了 就以第一个案例为主吧 ...

  2. 使用chrome调试前端线上代码

    家都知道在前端开发过程中,为加快网站静态资源加载速度都会对js/css等静态资源进行压缩合并再部署到生产环境,而在实际开发过程中开发人员一般都是在开发环境进行源码文件开发调试的,当部署平台或部署人员将 ...

  3. Synchronized修饰静态变量和普通变量的区别

    这里主要涉及到类对象(static方法),对象方法(非static方法) 我们知道,当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class本身,注意:不是实例): ...

  4. java自定义before和after

    package com.ada.wuliu.worker.web.cooperation.worker; public class TestOne { abstract class Father{ p ...

  5. 简单的js表单验证框架

    /** * 通常在我们的HTML页面表单中有大量的数据验证工作, * 免不了要写很多验证表单的js代码,这是一项非常繁琐 * 枯燥的工作.很多程序员也会经常遗漏这项工作.当然 * 一些JavaEE框架 ...

  6. 给js对象赋值,赋值key

    var pastResult = []; pastResult.push(feature.attributes.F_iID); pastResult.push(feature.attributes.F ...

  7. JavaScript toString() 方法

    注意:在JavaScript中,数字后面的"."操作符是的意义是不确定.因为它既可能是一个浮点数的标志,又可能是取一个对象的属性的运算符.但是JavaScript的解释器把他当做了 ...

  8. 如何运用spring将dao注入到servlet中?

    1.servlet的init方法 public void init(ServletConfig config) throws ServletException { super.init(config) ...

  9. Docker入门系列1:简介

    可以实现快速部署. 比如一台 16 核 32G 内存的虚拟机上,需要跑 500+ 个用户的应用(每个应用的功能可以认为是一个网站 + 一系列的 RESTful API),有两个事情很重要: 资源隔离: ...

  10. cocos2dx 3.2+ 项目创建与问题总汇

    本文为Cocos2d-x 3.x 全平台(Android,iOS)新手开发配置教程攻略,希望对大家有所帮助.由于这篇文章是面对新手的. 所以有些地方会啰嗦一些,请勿见怪. 假设教程中有错误.欢迎指正. ...