您的位置:首页 > 其它

(luogu P1383)高级打字机

2018-02-05 14:17 169 查看

高级打字机

题目链接 https://www.luogu.org/problemnew/show/P1383

背景

无聊中。。

随便在luogu上rand到了一道题

从此走上不归路

主席树是我暑假的时候学的

现在真的忘得精光

花了一个小时从零开始学

看来之前学过的东西还是要好好巩固啊

思路

首先50分超级好拿

纯粹的模拟就可以了

首先看到‘撤销’联想到‘历史版本’,于是就想到可以用主席树来支持这种撤销。

那主席树应该维护什么呢?

当然是维护输入的字符序列

由于一次更改肯定是基于上一次更改

所以和上一次有很多点是可以共用的

所以可以用可持久化数据结构

不过不同的是

由于序列的长度时增时减

所以我们需要一开始就把空间开足

然后这道题的读入也是一个坑点

YCB大佬亲自指导本菜鸡改读入(我还不会%c)教了我一种类似读入优化的读入一个字符的方法,比%c快(再也不用%c了)。

代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define rg register int
#define ll long long
#define RG register
#define il inline
using namespace std;

il int gi()
{
rg x=0,o=0;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||'9'<ch)) ch=getchar();
if(ch=='-') o=1,ch=getchar();
while('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return o?-x:x;
}

char ch,opt;int n;

#define SZ 100010

struct Tree { int l,r;char ch; }tr[SZ*25];
#define lson tr[rt].l
#define rson tr[rt].r
int Ed[SZ],tot,cnt;
// 主席树存什么? 每一个点的 字符
// 为什么不需要建树? 因为一开始是空的所以不需要建树,肯定不会跟空的共用节点

void update(int &rt,rg last,rg l,rg r,rg pos)
{
rt=++tot;
if(l==r) {tr[rt].ch=ch;return;}
lson=tr[last].l;rson=tr[last].r;
rg mid=l+r>>1;
if(pos<=mid) update(lson,tr[last].l,l,mid,pos);
else update(rson,tr[last].r,mid+1,r,pos);
}

char query(rg rt,rg l,rg r,rg pos)
{
if(l==r) return tr[rt].ch;
rg mid=l+r>>1;
if(pos<=mid) return query(lson,l,mid,pos);
else return query(rson,mid+1,r,pos);
}

int len[SZ];
int main()
{
n=gi();
while(n--)
{
opt=getchar();
while(opt!='T' && opt!='U' &&opt!='Q')opt = getchar();
if(opt=='T')
{
ch=getchar();
while(!('a'<=ch&&ch<='z')) ch=getchar(); // 把空格吃掉
len[++cnt]=len[cnt-1]+1;
update(Ed[cnt],Ed[cnt-1],1,SZ,len[cnt]);
}
if(opt=='U')
{
rg x=gi();
len[++cnt]=len[cnt-x-1];
Ed[cnt]=Ed[cnt-x-1];  // 还要 -1 想想为什么
}
if(opt=='Q')
{
rg x=gi();
printf("%c\n",query(Ed[cnt],1,SZ,x));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: