題解 P4008 NOI2003 文字編輯器

2022-06-12 01:27:08 字數 2426 閱讀 3670

link

在 \(insert\) 操作中可能存在換行符,你需要忽略掉它們,但是保證所有的字元的 ascii 碼在 \([32 ,126]\) 內。

保證 \(insert\) 操作插入的總長度不超過 \(2^\) 個。

保證游標不會移到非法位置,保證刪除,查詢的字元存在。

發現有區間插入,區間刪除,考慮用 \(splay\) 維護。

用乙個變數維護當前的游標位置,設這個變數叫做 \(pos\) 。

首先,為了防止越界,我們現在 \(splay\) 裡插入兩個 \(\backslash0\) ,防止越界。

之所以選擇 \(\backslash 0\) ,是因為把這個字元輸出來跟沒輸出一樣,對於 \(get\) 操作就不需要特判了。

乙個乙個操作看:

沒有這個操作!

我們先看看怎麼把乙個序列 \(a\) 建成一棵 \(splay\) 。

類似線段樹的建樹方法,設當前節點在序列中所對應的位置是 \([l,r]\) ,設 \(mid = (l+r)/2\) 。

我們讓這個節點的值為 $a[mid] $ ,然後左兒子對應的位置是 \([l,mid - 1]\) ,右兒子對應的位置就是 \([mid+1,r]\) 。

遞迴建樹即可。

這樣建出來的樹是平衡,高度為 \(\mathcal(\log_2 n)\) 。

直接讓 \(pos=k\) 即可。

我們在 \(splay\) 中找到排名為 \(pos+1\) 的節點(前面插入了乙個空節點,所以要 \(+1\) ),設這個節點為 \(ls\) 。

同時找到排名為 \(pos+2\) 的節點,設這個節點為 \(rs\) 。

把 \(ls\) 旋轉到根,把 \(rs\) 旋轉到 \(ls\) 下面,然後找到 \(rs\) 的左兒子,在這個左兒子下把這個插入的串用前面的 \(build\) 弄出來就行。

記得 \(pushup\) 。

在 \(splay\) 中找到排名為 \(pos+1\) 的節點(要刪除的區間開頭是 \(pos+1\) ,因為 \(splay\) 要找的是前乙個節點,但是又加上了乙個空節點,所以位置還是 \(pos+1\) ),記為 \(ls\) 。

再找到排名為 \(pos+len+2\) 的節點(要刪除的區間結尾是 \(pos+len\) ,前面有乙個空節點,然後又要找後乙個節點,所以是 \(pos+len+2\)) ,記為 \(rs\) 。

把 \(ls\) 旋轉到根,把 \(rs\) 旋轉到 \(ls\) 下面,直接刪除 \(rs\) 的左兒子即可。

和上面大同小異,只不過不是刪除 \(rs\) 的左兒子,而是輸出 \(rs\) 左兒子的中序遍歷。

讓 \(pos \to pos - 1\) 。

讓 \(pos\to pos + 1\) 。

思路倒是挺簡單,但是**有一點點難寫。

第一次一遍過。

#include #include #include inline int read() 

inline int min(int a ,int b)

inline int max(int a ,int b)

inline void swap(int &a ,int &b)

const int n = 1 << 22;

struct splay

}t[n]; int root ,tot;

splay () : root(0) ,tot(0) {}

inline void update(int now)

inline void rotate(int x)

inline void splay(int x ,int goal)

rotate(x);

}if (goal == 0) root = x;

}inline int findval(int rank)

return 0;

}inline void build(int &now ,int fa ,int l ,int r ,char *s)

inline void insert(int st ,int len ,char *s)

inline void remove(int a ,int b)

inline void dfs(int now)

inline void print(int a ,int b)

}t;char s[n] ,opt[10];

int n ,pos;

signed main()

t.insert(pos ,len ,s);

}else if (opt[0] == 'd')

else if (opt[0] =='g')

else if (opt[0] == 'p') pos--;

else if (opt[0] == 'n') pos++;

}return 0;

}

NOI2003 逃學的小孩 題解

前言 原題傳送門 洛谷 看了一下洛谷題面,這道noi的題竟然是藍的 惡評?做了一下好像確實是藍的.解法 思路非常簡單,找道樹的直徑,然後答案是直徑長度加上最大的min dis pos1 dis pos2 pos1和pos2是指定的任意一條直徑的兩個端點,dis是距離 證明 鑑於這是一棵樹 原題面 可...

P4408 NOI2003 樹的直徑

題意 傳送門 p4408 noi2003 逃學的小孩 題解設路徑 c,a c,a c,a 與路徑 a,b a,b a,b 的第乙個交點為 d dd,問題等價於從 a aa 出發,找到兩條路徑 a,b a,c a,b a,c a,b a,c 且滿足 dis t a,d d ist d,b dist a...

NOI2003 文字編輯器

很久很久以前,dos3.xdos3.xdos3.x 的程式設計師們開始對 edlinedlinedlin 感到厭倦。於是,人們開始紛紛改用自己寫的文字編輯器 多年之後,出於偶然的機會,小明找到了當時的乙個編輯軟體。進行了一些簡單的測試後,小明驚奇地發現 那個軟體每秒能夠進行上萬次編輯操作 當然,你不...