MY(一名蒟蒻)
2021-02-28 17:10:46
向辛苦审核题解的管理道歉,感谢指出排版错误,确实是我孤陋寡闻了。
P6166 [IOI2012]scrivener
蒟蒻my最近学了主席树,这可真是个好东西,他决定写篇题解加深下印象。
主席树,又名函数式线段树。由于发明人黄嘉泰的名字缩写和某位中国共产党领导人是一样的,故名主席树。
实现可持久化使用复制节点的方式,由于一次修改最多修改
弱化版 P1383 高级打字机 ,所谓挑战指的应该就是这题了。
首先没有初始版本,于是不需要建树。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e6+10;
int n,cnt,rt[N],tot;
struct node {int l,r,len; char c;} hjt[N << 5];
inline int clone(int now) {hjt[++cnt]=hjt[now]; return cnt;}//复制
int modify(int now,int l,int r,int p,char ch)
{
now=clone(now); hjt[now].len++;//只会修改log个节点,不用写pushup
if(l == r) {hjt[now].c=ch; return now;}
int mid=(l+r) >> 1;
if(p <= mid) hjt[now].l=modify(hjt[now].l,l,mid,p,ch);
else hjt[now].r=modify(hjt[now].r,mid+1,r,p,ch);
return now;
}
char query(int now,int l,int r,int p)
{
if(l == r) return hjt[now].c;
int mid=(l+r) >> 1;
if(p <= mid) return query(hjt[now].l,l,mid,p);
return query(hjt[now].r,mid+1,r,p);
}
int main()
{
// freopen("work.in","r",stdin); freopen("work.out","w",stdout);
scanf("%d",&n);
char op,ch;
int x;
for(int i=1;i<=n;i++)
{
scanf(" %c",&op);
if(op == 'T') {scanf(" %c",&ch); tot++; rt[tot]=modify(rt[tot-1],1,n,hjt[rt[tot-1]].len+1,ch);}//在最后插入新字符
if(op == 'U') {scanf("%d",&x); tot++; rt[tot]=rt[tot-x-1];}//指向旧版本,注意这个版本号
if(op == 'P') {scanf("%d",&x); printf("%c\n",query(rt[tot],1,n,x+1));}
}
// fclose(stdin); fclose(stdout);
return 0;
}
吐槽弱化版数据过水,空间只开
您的点赞和评论是对作者最大的支持!