1. 程式人生 > >【BZOJ 1269】 [AHOI2006]文本編輯器editor

【BZOJ 1269】 [AHOI2006]文本編輯器editor

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