jzoj3794,P1383-高级打字机【欧拉序,离线O(n)】
生活随笔
收集整理的這篇文章主要介紹了
jzoj3794,P1383-高级打字机【欧拉序,离线O(n)】
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題目鏈接:https://www.luogu.org/problemnew/show/P1383
大意
三個(gè)操作
T c:加入一個(gè)字符c
U x:撤銷(xiāo)前x次操作(只包括T和U)
Q x:詢問(wèn)當(dāng)前第x個(gè)字符
解題思路
對(duì)于50%的數(shù)據(jù)U不會(huì)撤銷(xiāo)到U
所以我們可以直接暴力
#include<cstdio> #include<iostream> using namespace std; int n,x,w; char c,a[100001]; int main() {scanf("%d\n",&n);for (int i=1;i<=n;i++){cin>>c;if (c=='U'){scanf("%d",&x);w-=x;}else if (c=='Q'){scanf("%d",&x);printf("%c\n",a[x]);}else{cin>>c;a[++w]=c;}} }然后正題——撤銷(xiāo)撤銷(xiāo)
你知道嗎?它的撤銷(xiāo)可以撤銷(xiāo)撤銷(xiāo)!
它還可以撤銷(xiāo)撤銷(xiāo)撤銷(xiāo)
還可以撤銷(xiāo)撤銷(xiāo)撤銷(xiāo)撤銷(xiāo)
……
好了,這道題支持離線算法所以我們就用離線算法。
離線算法我們要先構(gòu)一顆樹(shù),我們發(fā)現(xiàn)如果是TT操作的話可以直接和下一個(gè)版本相連然后加一個(gè)字母,如果是U xU x操作的話那么版本xx就等于版本x?k?1x?k?1,所以我們連邊
然后用歐拉序來(lái)求所有的版本,時(shí)間負(fù)責(zé)度O(n)O(n)
代碼
#include<cstdio> #include<iostream> #include<vector> #define MN 100011 using namespace std; vector<int> q[MN+1];//vertor庫(kù)儲(chǔ)存詢問(wèn) struct node{int to,next,w; }a[MN+1]; int p,x,k,tot,ls[MN+1],n,ans[MN+1]; char c,st[MN+1],s[MN+1]; void addl(int x,int y)//連邊 {a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot; } void dfs(int x,int sto)//歐拉序求答案 {for(int i=ls[x];i;i=a[i].next)dfs(a[i].to,sto);//自己搜索連接的版本if (s[x]) st[sto]=s[x],dfs(x+1,sto+1);//直接接到下一個(gè)版本for (int i=0;i<q[x].size();i++)ans[q[x][i]]=st[ans[q[x][i]]];//計(jì)算答案 } int main() {scanf("%d\n",&n);for (int i=1;i<=n;i++){cin>>c;if (c=='T'){cin>>s[k++];//標(biāo)記操作}else if (c=='Q'){scanf("%d",&x);q[k].push_back(++p);//記錄詢問(wèn)ans[p]=x;}else if (c=='U'){k++;scanf("%d",&x);addl(k-x-1,k);//連邊}}dfs(0,1);//求答案for (int i=1;i<=p;i++)if (ans[i]) printf("%c\n",ans[i]);//原序輸出 }總結(jié)
以上是生活随笔為你收集整理的jzoj3794,P1383-高级打字机【欧拉序,离线O(n)】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 腾讯《宝可梦大集结》手游国服开启预约,安
- 下一篇: 2018/7/10-纪中某C组题【jzo