【BZOJ 1269】 [AHOI2006]文本編輯器editor
阿新 • • 發佈:2018-04-22
c++ AC clas delete pen back 不知道 https 每次
【鏈接】 我是鏈接,點我呀:)
【題意】
在這裏輸入題意
【題解】
/*
【move k】 指令。直接 把pos改成k.表示改變光標位置
【insert n s】,在pos後面插入一個長度為n的字符串。
這個操作。
我們可以先找出第pos個節點x和第pos+1個節點y
(這裏其實就是找第pos小的數,在splay上,加一個size大小域,找第k小即可。)
(伸展樹在旋轉的過程中,不會影響性質,即,它中序遍歷的結果始終是字符串s1..n)
我們執行splay x 0
再執行splay y x
然後顯然y節點在x的右兒子上。
那麽,此時,我們新建一顆節點為插入的字符串的子樹root
然後把root放在y的左子樹
然後我們新建一顆子樹,把它加在y的左兒子上。
我們在插入節點的時候。放在左兒子和右兒子。
其實就是約束了這個點和其父親節點的先後關系。
左兒子在前.右兒子的話就是在後。
也正因為如此。
我們才能保證中序遍歷結果為s[1..n]
【delete(n)】 找出第pos個節點x和第pos+1+n個節點y.然後同樣的splay(x,0)、splay(y,x),然後把y的左子樹刪掉就可以了。
【rotate n】一樣。找到pos和pos+1+n兩個節點x,y 然後spay(x,0),splay(y,x) 然後把y的左兒子打上翻轉標記。(這裏後序的我不知道怎麽處理
(什麽時候要push_down?
【get】就直接輸出第pos個節點的字符就好。
【prev】 pos--;
【next] pos++;
*/
【註意】
push_down只要加在Rank函數的開頭就好。
因為每次從根到root.
一路上都會把標記給Push_down了
那麽rotate裏面就不需要push_down了。
【代碼】
#include <bits/stdc++.h>
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define which(x) (ch[fa[x]][1]==x)
using namespace std;
const double pi = acos(-1);
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};
const int N = 2*1024*1024;
int n,siz[N+100],fa[N+10],tag[N+10],tot,pos;
int ch[N+10][2],root;
char s[10],S[N+10],str[N+10];
void push_up(int x){
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
void push_down(int x){
if (tag[x]>0){
tag[x] = 0;
tag[ch[x][0]]^=1;tag[ch[x][1]] ^= 1;
swap(ch[x][0],ch[x][1]);
}
}
int Rank(int x, int k)
{
push_down(x);
if (siz[ch[x][0]] >= k)
return Rank(ch[x][0], k);
else
if (k == siz[ch[x][0]] + 1)
return x;
else
return Rank(ch[x][1], k - siz[ch[x][0]] - 1);
}
void Rotate(int x)
{
int f = fa[x];
bool k = which(x);
ch[f][k] = ch[x][!k];
ch[x][!k] = f;
ch[fa[f]][which(f)] = x;
fa[ch[f][k]] = f;
fa[x] = fa[f];
fa[f] = x;
siz[x] = siz[f];
push_up(f);
}
void Splay(int x, int g)
{
while (fa[x] != g)
{
int f = fa[x];
if (fa[f] == g)
{
Rotate(x);
break;
}
if (which(x) ^ which(f))
Rotate(x);
else
Rotate(f);
Rotate(x);
}
if (!g) root = x;
}
int build(int l, int r, int rt) //創建一顆新的子樹。
{
if (l > r) return 0;
int mid = (l + r) >> 1;
int x = ++tot;
fa[x] = rt; str[x] = S[mid];
ch[x][0] = build(l, mid - 1, x);
ch[x][1] = build(mid + 1, r, x);
push_up(x);
return x;
}
int main(){
#ifdef LOCAL_DEFINE
freopen("rush_in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0),cin.tie(0);
root = 1;
tot++;str[tot] = '@';siz[tot] = 2;ch[tot][1] = tot+1;
tot++;str[tot] = '#';siz[tot] = 1;fa[tot] = 1;
//創建兩個邊界節點。
cin >> n;
while (n--){
cin >> s;
//cout<<s<<endl;
if (s[0]=='M'){
int k;
cin >> k;
pos = k;
}else if (s[0]=='P'){
pos--;
}else if (s[0]=='N'){
pos++;
}else if (s[0]=='I'){
int len;
cin >> len;cin.get();
cin.getline(S,N);
int x = Rank(root,pos+1),y = Rank(root,pos+1+1);
Splay(x,0);Splay(y,x);
ch[y][0] = build(0,len-1,y);
push_up(y);push_up(x);
Splay(y,0);
}else if (s[0]=='D'){
int len;
cin >> len;
int x = Rank(root,pos+1),y = Rank(root,pos+1+len+1);
Splay(x,0);Splay(y,x);
ch[y][0] = 0;
push_up(y);push_up(x);
Splay(y,0);
}else if (s[0]=='R'){
int len;
cin >> len;
int x = Rank(root,pos+1),y = Rank(root,pos+1+len+1);
Splay(x,0);Splay(y,x);
int t = ch[y][0];
tag[t] ^= 1;
}else if (s[0]=='G'){
int x = Rank(root,pos+2);
cout<<str[x]<<endl;
}
}
return 0;
}
【BZOJ 1269】 [AHOI2006]文本編輯器editor