1. 程式人生 > >jzoj3658. 【NOI2014模擬】文字編輯器(editor)

jzoj3658. 【NOI2014模擬】文字編輯器(editor)

題目描述

Description 在這裡插入圖片描述 Input 在這裡插入圖片描述 Output 對於每個詢問輸出一個字元表示答案。

Sample Input 9 I 0 o I 0 r I 0 z R 1 3 Q 1 D 1 1 Q 1 C 2 2 0 Q 1

Sample Output orz

Data Constraint 在這裡插入圖片描述

題解

因為有複製操作,所以要用可持久化平衡樹來搞 其它操作相同,複製操作時先複製根,然後取出要複製的節點(split*2),最後插入(split*1,merge*2)

因為是區間操作,所以下傳標記時也要新建孩子節點

優化

1、每次如果有標記才下傳(新建節點) 2、(自己想的)如果一個節點有多條邊指向它時才新建 比較玄學,但很有效 要注意當一個點只剩一個父親時,記錄的父親可能會錯 比如這樣 在這裡插入圖片描述

其中黑色邊表示向下指向孩子的邊,紅色邊表示記錄的父親,灰色邊表示將要複製的邊(即非原本父親指向它的邊) 然後新建節點後變成了這樣 在這裡插入圖片描述 顯然下面的節點的父親錯了 解決方法是每次向下走時都將兒子的父親設為當前點,這樣一定能保證其正確性 就算當前的父親時錯的也無所謂,因為最後只剩一個父親時一定是對的

3、(構思中)每次把下傳標記分成左右兒子分別下傳,然後再記錄每條邊出現時複製的原節點,之後只有向某一方向走時才新建節點 不過這樣複製資訊就會很eggache,反正都過了就無所謂了

4、查詢時可以不同新建節點,只需要記錄下當前的兒子是否翻轉 向下走就異或一下左/右兒子的編號(0/1)

5、隨機的值可以不用陣列記錄,只需要 r

and()%(size[a]+size[b])<size[a]rand()\%(size[a]+size[b])<size[a] 這樣可以使保證子樹較大的樹高概率被放在上面,使樹高均攤log  nlog\;n

6、O3大法好 2000byte的O3問你怕不怕

*7、OJ上的隨機數範圍是0~2147483647,而本地是0~32767 馬德坑了我兩個禮拜

code

#include <iostream>
#include <cstdlib>
#include
<cstdio>
#include <ctime> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define Max 20000001 using namespace std; int tr[Max][2]; int sum[Max]; int fa[Max]; int num[Max]; bool rev[Max]; int FA[Max]; //nµÄ¸¸Ç׸öÊý int N,n,Q,i,j,k,l,x,y,z,X,Fs,Ls,I,J,root,Find,Find2,now,fa1,fa2,Root,ROOT,root2; char type,ch; inline int getint() {char c; register int ret=0; for(c=getchar(); c<'0' || c>'9'; c=getchar()); for(; c>='0'&&c<='9'; c=getchar()) ret=ret*10+c-'0'; return ret; } inline char getChar() { char ch=getchar(); for (; ch<'A' || ('Z'<ch && ch<'a') || 'z'<ch; ch=getchar()); return ch; } inline void up(register int t) {sum[t]=sum[tr[t][0]]+sum[tr[t][1]]+1;} inline void swap(register int &a,register int &b) {int c=a;a=b;b=c;} inline int copy(register int root) { if (now) { n++; tr[n][0]=tr[root][0]; FA[tr[n][0]]++; tr[n][1]=tr[root][1]; FA[tr[n][1]]++; num[n]=num[root]; sum[n]=sum[root]; rev[n]=rev[root]; } return n; } inline void down(register int t) { if (rev[t] && t) { swap(tr[t][0],tr[t][1]); rev[tr[t][0]]^=1; rev[tr[t][1]]^=1; rev[t]=0; } } inline void New(register int t,register int x) { if (t && tr[t][x]) { fa[tr[t][x]]=t; if (FA[tr[t][x]]>1)//優化2 { FA[tr[t][x]]--; n++; tr[n][0]=tr[tr[t][x]][0]; FA[tr[n][0]]++; tr[n][1]=tr[tr[t][x]][1]; FA[tr[n][1]]++; sum[n]=sum[tr[t][x]]; fa[n]=t; //not fa[tr[t][x]] num[n]=num[tr[t][x]]; rev[n]=rev[tr[t][x]]; FA[n]=1; tr[t][x]=n; } } } inline void merge(register int Fa,register int son,register int x,register int y) { if (x && rev[x]) New(x,0),New(x,1),down(x);//優化1 if (y && rev[y]) New(y,0),New(y,1),down(y); if (rand()%(sum[x]+sum[y])<sum[x])//優化5 { if (Root==-1) Root=x; New(x,1); tr[Fa][son]=x; FA[x]+=(!fa[x] && Fa); fa[x]=Fa; if (tr[x][1]) merge(x,1,tr[x][1],y); else { if (x) { sum[x]+=sum[y]; tr[x][1]=y; } FA[y]+=(!fa[y]); fa[y]=x; } } else { if (Root==-1) Root=y; New(y,0); tr[Fa][son]=y; FA[y]+=(!fa[y] && Fa); fa[y]=Fa; if (tr[y][0]) merge(y,0,x,tr[y][0]); else { if (y) { sum[y]+=sum[x]; tr[y][0]=x; } FA[x]+=(!fa[x]); fa[x]=y; } } if (Fa) up(Fa); } inline void split(register int Fa1,register int Fa2,register int t,register int k) //fa1±íʾºó°ë¶ÎµÄ¸ù£¬fa2±íʾǰ°ë¶ÎµÄ¸ù { if (rev[t]) New(t,0),New(t,1),down(t); if (sum[tr[t][0]]>=k) { New(t,0); if (!fa1) fa1=t; if (fa[t]) { FA[t]-=(!Fa1); tr[fa[t]][tr[fa[t]][1]==t]=0; up(fa[t]); } tr[Fa1][0]=t; fa[t]=Fa1; if (k && tr[t][0]) split(t,Fa2,tr[t][0],k); if (Fa1) up(Fa1); } else { New(t,1); if (!fa2) fa2=t; if (fa[t]) { FA[t]-=(!Fa2); tr[fa[t]][tr[fa[t]][1]==t]=0; up(fa[t]); } tr[Fa2][1]=t; fa[t]=Fa2; if (tr[t][1]) split(Fa1,t,tr[t][1],k-sum[tr[t][0]]-1); if (Fa2) up(Fa2); } } inline int find(register int t,register int k,register bool Rev) { Rev^=rev[t]; //優化4 if (sum[tr[t][Rev]]>=k) return find(tr[t][Rev],k,Rev); else if (sum[tr[t][Rev]]+1==k) return num[t]; else return find(tr[t][!Rev],k-sum[tr[t][Rev]]-1,Rev); } int main() { freopen("editor.in","r",stdin); freopen("editor.out","w",stdout); srand(time(NULL)); Q=getint(); n=0; now=0; fo(I,1,Q) { type=getChar(); switch (type) { case 'I': { x=getint(); ch=getChar(); n++;N=n; num[n]=ch-'a'; sum[n]=1; if (!now) root=N; else { Root=-1; if (!x) merge(0,0,N,root); else if (x==now) merge(0,0,root,N); else { fa1=0;fa2=0; split(0,0,root,x); merge(0,0,fa2,N); ROOT=Root; Root=-1; merge(0,0,ROOT,fa1); } root=Root; } now++; break; } case 'D': { x=getint(); y=getint(); j=0;k=0; if (x>1) { fa1=0;fa2=0; split(0,0,root,x-1); j=fa2; root=fa1; } if (y<now) { fa1=0;fa2=0; split(0,0,root,y-x+1); k=fa1; } if (j && k) { Root=-1; merge(0,0,j,k); root=Root; } else if (j) root=j; else if (k) root=k; now-=(y-x+1); break; } case 'C': { x=getint(); y=getint(); z=getint(); root2=copy(root); j=0;k=0; if (x>1) { fa1=0;fa2=0; split(0,0,ro