★★★ 輸入檔案:editor2003.in
輸出檔案:editor2003.out
簡單對比
時間限制:2 s 記憶體限制:128 mb
【問題描述】
很久很久以前,dos3.x的程式設計師們開始對edlin感到厭倦。於是,人們開始紛紛改用自己寫的文字編輯器……
多年之後,出於偶然的機會,小明找到了當時的乙個編輯軟體。進行了一些簡單的測試後,小明驚奇地發現:那個軟體每秒能夠進行上萬次編輯操作(當然,你不能手工進行這樣的測試)!於是,小明廢寢忘食地想做乙個同樣的東西出來。你能幫助他嗎? 為了明確任務目標,小明對「文字編輯器」做了乙個抽象的定義:
文字:由0個或多個字元構成的序列。這些字元的ascii碼在閉區間[32, 126]內,也就是說,這些字元均為可見字元或空格。
游標:在一段文字中用於指示位置的標記,可以位於文字的第乙個字元之前,文字的最後乙個字元之後或文字的某兩個相鄰字元之間。
文字編輯器:為乙個可以對一段文字和該文字中的乙個游標進行如下六條操作的程式。如果這段文字為空,我們就說這個文字編輯器是空的。
操作名稱
輸入檔案中的格式
功能move(k)
move k
將游標移動到第k個字元之後,如果k=0,將游標移到文字第乙個字元之前
insert(n, s)
insert n↵
s在游標後插入長度為n的字串s,游標位置不變,n ≥ 1
delete(n)
delete n
刪除游標後的n個字元,游標位置不變,n ≥ 1
get(n)
get n
輸出游標後的n個字元,游標位置不變,n ≥ 1
prev()
prev
游標前移乙個字元
next()
next
游標後移乙個字元
比如從乙個空的文字編輯器開始,依次執行操作insert(13, 「balanced□tree」),move(2),delete(5),next(),insert(7, 「□editor」),move(0),get(15)後,會輸出「bad□editor□tree」,如下表所示:
操作操作前的文字
操作後的結果
insert(13, "balanced□tree")
|(只有游標,文字為空)
|balanced□tree
move(2)
|balanced□tree
ba|lanced□tree
delete(5)
ba|lanced□tree
ba|d□tree
next()
ba|d□tree
bad|□tree
insert(7, "□editor")
bad|□tree
bad|□editor□tree
move(0)
bad|□editor□tree
|bad□editor□tree
get(15)
|bad□editor□tree
輸出「bad□editor□tree」
上表中,「|」表示游標,「□」表示空格。 你的任務是:
【輸入檔案】
輸入檔案的第一行是指令條數t,以下是需要執行的t個操作。其中:
為了使輸入檔案便於閱讀,insert操作的字串中可能會插入一些回車符,請忽略掉它們(如果難以理解這句話,可以參考樣例)。
除了回車符之外,輸入檔案的所有字元的ascii碼都在閉區間[32, 126]內。且行尾沒有空格。 這裡我們有如下假定:
【輸出檔案】
輸出檔案的每行依次對應輸入檔案中每條get指令的輸出。
【樣例輸入】
15【樣例輸出】insert 26
abcdefghijklmnop
qrstuv wxy
move 15
delete 11
move 5
insert 1
^next
insert 1
_next
next
insert 4
.\/.
get 4
prev
insert 1
^move 0
get 22
.\/.
abcde^_^f.\/.ghijklmno題解:
本題用splay來維護,我們先在splay中插入兩個'*'表示在序列的開端和結尾各有乙個'*'方便以後處理,pos記錄當前游標所在位置,因為在序列開頭加上了'*',所以pos=游標所在的位置+1。
對於插入操作,可以先把要插入的序列建成一棵splay,假設游標在第k個字元的後面,那麼讓第k-1個字元旋至根,第k個字元旋至根的右孩子,所要加入的區間就是根的右孩子的左邊那一塊,直接把剛建好的splay插入。
刪除操作就是找到要刪除區間的左端點,把它旋至根,找到要刪除區間的右端點,把它旋至根的右孩子,要刪除的區間就是根的右孩子的左邊那一塊,直接刪除即可。
剩下的操作就是直接對pos的操作,很好理解。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9using
namespace
std;
10 typedef long
long
ll;11
const
int maxn=3000000;12
introot,tot,fa[maxn],lc[maxn],rc[maxn],siz[maxn];
13int t,n,pos=1;14
char opt[20
],ch[maxn],key[maxn];
15 inline void update(int
x)18 inline void r_rotate(int
x)28 inline void l_rotate(int
x)38 inline void splay(int x,int
s)47
else
if(x==lc[p])
51else
if(x==rc[p])55}
56if(s==0) root=x;57}
58 inline int find(int x,int
rank)
63 inline void split(int l,int
r)67 inline void newnode(int &x,char ch,int
fath)
72 inline void insert(int &x,int l,int r,int
fath)
79 inline void
delete()
84 inline void print(int
x)89 inline void
get()
93int
main()
109 split(pos+1,pos);//
分割游標和游標的下一位
110 insert(lc[rc[root]],1
,n,rc[root]);
111update(rc[root]); update(root);
112break
;113
case'd
':114 scanf("
%d",&n);
115delete();
116break
;117
case'g
':118 scanf("
%d",&n);
119 get(); printf("\n"
);120
break
;121
case'p
':122 pos--; break
;123
case'n
':124 pos++; break
;125
}126
}127
return0;
128 }
NOI2003 文字編輯器
很久很久以前,dos3.xdos3.xdos3.x 的程式設計師們開始對 edlinedlinedlin 感到厭倦。於是,人們開始紛紛改用自己寫的文字編輯器 多年之後,出於偶然的機會,小明找到了當時的乙個編輯軟體。進行了一些簡單的測試後,小明驚奇地發現 那個軟體每秒能夠進行上萬次編輯操作 當然,你不...
NOI2003 文字編輯器
題目 發現這樣一句話就會導致 t ch m 0 m 並不是很知道為什麼,可能這是某種未定義行為在不同編譯器下會有不同後果?至於這道題就很簡單了,幾個有關游標位置的操作就用乙個變數模擬就好了 插入的話把這個位置轉出來構造一棵完美 splay 插入就好了 刪除直接轉出區間斷開的父親的鏈結 輸出直接轉出區...
題解 P4008 NOI2003 文字編輯器
link 在 insert 操作中可能存在換行符,你需要忽略掉它們,但是保證所有的字元的 ascii 碼在 32 126 內。保證 insert 操作插入的總長度不超過 2 個。保證游標不會移到非法位置,保證刪除,查詢的字元存在。發現有區間插入,區間刪除,考慮用 splay 維護。用乙個變數維護當前...