C51 可持久化线段树 P1383 高级打字机
视频链接:237 可持久化线段树 P1383 高级打字机_哔哩哔哩_bilibili
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=100005; #define mid ((l+r)>>1) int root[N],tot,cnt; int ls[N*20],rs[N*20],sum[N*20]; char ch[N*20]; //tot:节点个数, cnt:根节点个数 //sum:区间内的字母数 //ch: 叶子节点上的字母 void pushup(int u){ //上传 sum[u]=sum[ls[u]]+sum[rs[u]]; } void change(int &u,int v,int l,int r,char c){ //点修 u=++tot; //动态开点 ls[u]=ls[v];rs[u]=rs[v];sum[u]=sum[v]; if(l==r){sum[u]=1;ch[u]=c;return;} //双指针同步搜索 if(sum[ls[u]]<mid-l+1) change(ls[u],ls[v],l,mid,c); else change(rs[u],rs[v],mid+1,r,c); pushup(u); } char query(int u,int l,int r,int x){ //点查 if(l==r) return ch[u]; if(x<=sum[ls[u]]) return query(ls[u],l,mid,x); else return query(rs[u],mid+1,r,x-sum[ls[u]]); } int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ char o,c; int x; cin>>o; if(o=='T'){ //在文章末尾添加一个字母 cin>>c; ++cnt; change(root[cnt],root[cnt-1],1,n,c); } if(o=='U'){ //撤销最后的x次修改操作 cin>>x; ++cnt; root[cnt]=root[cnt-x-1]; } if(o=='Q'){ //查询第x个字母 cin>>x; cout<<query(root[cnt],1,n,x)<<endl; } } return 0; }
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=100005; #define mid ((l+r)>>1) int root[N],tot,cnt; int ls[N*20],rs[N*20],sum[N*20]; char ch[N*20]; //tot:节点个数, cnt:根节点个数 //sum:区间内的字母数 //ch: 叶子节点上的字母 void change(int &u,int v,int l,int r,char c){ //点修 u=++tot; //动态开点 ls[u]=ls[v];rs[u]=rs[v];sum[u]=sum[v]+1; if(l==r){sum[u]=1;ch[u]=c;return;} //双指针同步搜索 if(sum[ls[u]]<mid-l+1) change(ls[u],ls[v],l,mid,c); else change(rs[u],rs[v],mid+1,r,c); } char query(int u,int l,int r,int x){ //点查 if(l==r) return ch[u]; if(x<=sum[ls[u]]) return query(ls[u],l,mid,x); else return query(rs[u],mid+1,r,x-sum[ls[u]]); } int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ char o,c; int x; cin>>o; if(o=='T'){ //在文章末尾添加一个字母 cin>>c; ++cnt; change(root[cnt],root[cnt-1],1,n,c); } if(o=='U'){ //撤销最后的x次修改操作 cin>>x; ++cnt; root[cnt]=root[cnt-x-1]; } if(o=='Q'){ //查询第x个字母 cin>>x; cout<<query(root[cnt],1,n,x)<<endl; } } return 0; }