【题目链接luogu】

这是T1,但是是神仙T1:

对于前100%的数据很好写,直接数组模拟就可以了:

(当然也有栈模拟的,据说有模拟炸了的)

//50pts
#include<bits/stdc++.h> using namespace std; inline int read() {
int ans=;
char last=' ',ch=getchar();
while(ch>''||ch<'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} char Getchar() {
char ch=' ';
do {
ch=getchar();
} while(ch==' '||ch=='\n'||ch=='\0'||ch=='\t'||ch=='\r');
return ch;
} int n,num;
char ops;
char s[]; int main() {
n=read();
int zz=;
for(int i=; i<=n; i++) {
ops=Getchar();
if(ops=='T') {
s[zz]=Getchar();
zz++;
}
if(ops=='Q') {
num=read();
printf("%c\n",s[num]);
}
if(ops=='U') {
num=read();
zz-=num;
}
}
return ;
}

然后真的要安利的一点:手写读入char字符Getchar;

从water_lift姐姐那偷师学来的,然后真的好用,可以过滤多余的空格回车换行制表符……

这样与读入的斗争就会简单了呢qwq;

然后来看100pts思路;

我们可以建立n个栈(用数组模拟),

每一个栈储存第n次操作(应该是不算查询的)后序列的样子

看样例:

7
T a
T b
T c
Q 2
U 2
T c
Q 2

T 2:

现在有2个栈,一个为空栈,一个为插入了一个元素a后的栈;

T b:

将栈1先复制给栈2,然后在栈2中插入一个b;

T c:

同理,现在共有四个栈;

Q 2:

直接用数组下标查询最后一个栈中的元素(因为我们用数组模拟的栈),可以做到O(1)查询;

U 2:

需要撤销两步,咋的办呢?我们就将当前操作的序号(为4)(不算查询)减1再减2(也就是需要撤销的步数),然后将其的栈拷贝过来(这样就可以应对撤销撤销撤销了):

然后这个思路,除了空间会爆,没有什么缺点

但是我们可以对这个思路进行优化:

试想一下,当n越大,栈中需要拷贝的数,可能增多,尤其是当出现撤销插入撤销插入的毒瘤数据时,你剩下的几百个元素吧,都没有用到,但是你每次都需要把它拷贝一遍,明显是即占空间又占时间的;

因此我们可以考虑链表维护:

对于每一个链表当中的结点,我们维护两个数据,第一个是这个结点的字母,第二个是这个结点上一个结点是哪一个:

这样当插入时,我们只需要新建一个结点将新插入的字符写到字母数据中,将nxt指向上一个结点就可以了;

当需要撤销时,同样新建一个结点,并且将这个结点拷贝成(当前操作数-1-撤销步数)这个结点的信息(表示撤销了撤销步数步操作),下次再添加时,直接在当前结点的基础上加就好了;

考虑一下复杂度,我们可以做到O(1)插入,O(1)撤销,但是查询却需要O(n),这也不够优秀,我们还需改进;

考虑分块来做,我们设置一个最长长度B(动态维护B为√n),对于插入和撤销,还是像上面一样,只是当插入的时候,我们判断当前这个块有没有满,若没满,直接在后面插入,否则,新建一个块,再插入。

然后对于查询,我们知道了x和一个块的大小B,我们可以先跳过x/B(整除好评qwq)个块,然后再从x所在的块里面寻找x。因为我们模拟链表只能从后往前找,所以实际上我们需要算的是 总的元素个数-x+1;

对于这套思路,还是可以理解的,但是作为noip选手,到现在都(jiao)没(lian)有(bu)学(rang)指针,因此除了代码实现,莫得什么问题了呢qwq;

nili water_lift姐姐的代码:

#include <cmath>
#include <cstdio>
#include <cstring>
template <class T>
inline void read(T &num)
{
bool flag = ;
num = ;
char c = getchar();
while ((c < '' || c > '') && c != '-')
c = getchar();
if (c == '-')
{
flag = ;
c = getchar();
}
num = c - '';
c = getchar();
while (c >= '' && c <= '')
num = (num << ) + (num << ) + c - '', c = getchar();
if (flag)
num *= -;
}
inline void read(char &c)
{
do
{
c = getchar();
} while (c == ' ' || c == '\n' || c == '\r');
}
template <class T>
inline void output(T num)
{
if (num < )
{
putchar('-');
num = -num;
}
if (num >= )
output(num / );
putchar(num % + '');
}
template <class T>
inline void outln(T num)
{
output(num);
putchar('\n');
}
template <class T>
inline void outps(T num)
{
output(num);
putchar(' ');
}
template <class T>
inline T max(T a, T b) { return a < b ? b : a; }
const int N = ;
int n, B;
struct node
{
char *s;
int now, pc;
node *pre;
node()
{
now = pc = ;
s = new char[B];
pre = NULL;
}
void copy(node *src)
{
now = src->now;
pc = src->pc;
pre = src->pre;
for (int i = ; i < now; i++)
{
s[i] = src->s[i];
}
}
} * head[N];
int lst;
void append(char x)
{
if (head[lst]->now == B)
{
head[++lst] = new node;
head[lst]->pre = head[lst - ];
head[lst]->pc = head[lst - ]->pc + ;
head[lst]->s[head[lst]->now++] = x;
}
else
{
head[++lst] = new node;
head[lst]->copy(head[lst - ]);
head[lst]->s[head[lst]->now++] = x;
}
}
char query(int x)
{
int siz = head[lst]->now + head[lst]->pc * B;
x = siz - x + ;
if (x <= head[lst]->now)
{
return head[lst]->s[head[lst]->now - x];
}
x -= head[lst]->now;
node *now = head[lst]->pre;
while (x > B)
{
now = now->pre;
x -= B;
}
return now->s[B - x];
}
int main()
{
read(n);
B = sqrt(n);
head[] = new node;
for (int i = ; i <= n; i++)
{
char op;
read(op);
if (op == 'T')
{
char x;
read(x);
append(x);
}
if (op == 'U')
{
int x;
read(x);
head[lst + ] = head[lst - x];
lst += ;
}
if (op == 'Q')
{
int x;
read(x);
putchar(query(x));
putchar('\n');
}
}
}

end-

【7.10校内test】T1高级打字机的更多相关文章

  1. [模拟赛] T1 高级打字机

    Description 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小 ...

  2. Bzoj 3333 高级打字机(主席树)

    3333 高级打字机 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能 ...

  3. 洛谷 P1383 codevs 3333 高级打字机

    题目描述 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小写字母x.(t ...

  4. 2021.07.02 P1383 高级打字机题解(可持久化平衡树)

    2021.07.02 P1383 高级打字机题解(可持久化平衡树) 分析: 从可以不断撤销并且查询不算撤销这一骚操作可以肯定这是要咱建一棵可持久化的树(我也只会建可持久化的树,当然,还有可持久化并查集 ...

  5. C++之路进阶——codevs3333(高级打字机)

    3333 高级打字机  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master     题目描述 Description 早苗入手了最新的高级打字机.最新款自然有着与 ...

  6. (luogu P1383)高级打字机

    高级打字机 题目链接 https://www.luogu.org/problemnew/show/P1383 背景 无聊中.. 随便在luogu上rand到了一道题 从此走上不归路 主席树是我暑假的时 ...

  7. P1383 高级打字机

    P1383 高级打字机 主席树 一发主席树解决. 插入操作十分显然. 撤销操作复制前面的版本就行. 询问操作十分显然. #include<iostream> #include<cst ...

  8. codevs 3333 高级打字机

    3333 高级打字机   题目描述 Description 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作 ...

  9. NOIP模拟赛 高级打字机

    [题目描述] 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小写字母x. ...

随机推荐

  1. buuctf@rip

    exp: from pwn import * buf_start = 0x00007FFDBD754931 buf_end = 0x00007FFDBD754948 func_fun_addr= 0x ...

  2. ROM和RAM的内存详细说明

    1.首先是ROM 的读取是需要提前两个地址的读取,所以要想读取0地址的数据,你需要给地址是2 2.关于宽度,深度的计算 假设我们要存取如下取模的数据,该模的设置口语描述为:这是显示的2个字节,其中一个 ...

  3. Cloud Computing——Everything as a Service

    service 分类 有Iaas, Paas, SaaS HDFS 总结☞: HDFS应付不了的场景 无法低时延 小文件存储存在空间利用率问题 文件不可修改 三副本有什么作用 防止单机故障,提高可用性 ...

  4. [BZOJ2654]:tree(Kruskal+WQS二分)

    题目传送门 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树.题目保证有解. 输入格式 开始标号),边权,颜色(0白色1黑色). 输出格式 一行表 ...

  5. Java并发编程的艺术笔记(一)——volatile和syncronized关键字

    一.线程间的通信 volatile和syncronized关键字 volatile 修饰变量,告知任何对该变量的访问必须从共享内存获取,对它的改变必须同步刷新至共享内存,由此保证可见性. syncro ...

  6. Hive数据导入Elasticsearch

    Elasticsearch Jar包准备 所有节点导入elasticsearch-hadoop-5.5.1.jar /opt/cloudera/parcels/CDH-5.12.0-1.cdh5.12 ...

  7. 在linux下搭建go环境

    这几天小Jerry开始接触Go语言了,因为小Jerry学个东西必须要从最基础的开始弄懂,不然~她理解不了<hahaha> 所以,今天就来讲最基础,却也很容易让小Jerry这样的菜鸟感到困扰 ...

  8. C#实现读取指定盘符硬盘序列号的方法

      文章主要介绍了C#实现读取指定盘符硬盘序列号的方法,涉及C#针对硬件属性的相关操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例讲述了C#实现读取指定盘符硬盘序列号的方法.分享给大家供 ...

  9. async await task.Result 卡死

    在如下代码中: public async Task<string> GetData() { return await DoWork(); } 在UI线程中调用 var data = Get ...

  10. leetcode-easy-array-189 Rotate Array

    mycode  75.59% class Solution(object): def rotate(self, nums, k): """ :type nums: Lis ...