jzoj3658. 【NOI2014模擬】文字編輯器(editor)
阿新 • • 發佈:2018-12-13
題目描述
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、隨機的值可以不用陣列記錄,只需要 這樣可以使保證子樹較大的樹高概率被放在上面,使樹高均攤
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