传送门:loj2341
题解
链要求的复杂度
n
+
log
n
n+\log n
n+logn
树要求的复杂度
n
log
n
n\log n
nlogn
显然要单独考虑链的情况:
从
1
1
1开始维护端点
l
,
r
l,r
l,r表示已知的区间
[
l
,
r
]
[l,r]
[l,r],每次新加入点和
l
l
l查询一次判断该点在区间左侧/右侧,把端点不断移过去即可。
时间复杂度期望下 n + ln n n+\ln n n+lnn
树的情况:
比较显然的暴力把1当做根,每次新加入点和 1 1 1查询得到的点必然是 1 1 1的儿子,如果已知且不是新加入点就不断向下走。复杂度 O ( n 2 ) O(n^2) O(n2)
考虑动态点分治使得树高为 log n \log n logn,运用替罪羊树暴力重构的思想维护。
同样也可以简单地用LCT维护这个过程,每次在重链上二分,如果不在重链上就直接向下跳虚儿子。
比较好写但常数大。
然而两个方法我的代码都被卡了TAT
代码
两份都被卡了只有90+
LCT
#include<bits/stdc++.h>
#include"rts.h"
using namespace std;
const int N=3e5+10;
int n,id[N];
bool col[N];
inline void sp()
{
int i,j,x,v,l=1,r=1;
for(int i=1;i<n;++i) if(!col[id[i]]){
x=id[i];v=explore(l,x);
if(!col[v]){
for(;;v=explore(l,x)){
col[(l=v)]=true;
if(v==x) break;
}
}else{
for(;;){
v=explore(r,x);
col[(r=v)]=true;
if(v==x) break;
}
}
}
}
namespace LCT{
#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
#define F(x) t[x].fa
#define notrt(x) ((F(x))&&((lc(F(x))==x)||(rc(F(x))==x)))
struct node{int ch[2],fa,l,r;}t[N];
inline void pu(int x)
{
t[x].l=t[x].r=x;
if(lc(x)) t[x].l=t[lc(x)].l;
if(rc(x)) t[x].r=t[rc(x)].r;
}
inline void rot(int x){
int y=F(x),z=F(y),dr=(rc(y)==x);
t[y].ch[dr]=t[x].ch[dr^1];
if(t[y].ch[dr]) F(t[y].ch[dr])=y;
F(x)=z;if(notrt(y)) t[z].ch[rc(z)==y]=x;
F(y)=x;t[x].ch[dr^1]=y;pu(y);pu(x);
}
inline void splay(int x)
{
int y,z;
for(;notrt(x);rot(x)){
y=F(x);z=F(y);
if(notrt(y))
((rc(y)==x)^(rc(z)==y))?rot(x):rot(y);
}
pu(x);
}
inline void setrs(int x,int rs){splay(x);rc(x)=rs;pu(x);}
inline void aces(int x)
{for(setrs(x,0);F(x);x=F(x)) setrs(F(x),x);}
}
using namespace LCT;
void play(int nn,int T,int dataType)
{
srand(1732);
col[1]=true;n=nn;
for(int i=1;i<n;++i) id[i]=i+1;
random_shuffle(id+1,id+n);
if(dataType==3) sp();
else{
int i,x,v,nw;splay(1);
for(i=1;i<n;++i) if(!col[id[i]]){
x=id[i];
for(splay((nw=1));nw^x;){
v=explore(nw,x);
if(v==t[rc(nw)].l) nw=rc(nw);
else if(v==t[lc(nw)].r) nw=lc(nw);
else if(col[v]){splay(v);nw=v;}
else{col[v]=true;F(v)=nw;pu((nw=v));}
}
aces(x);
}
}
}
动态点分治
#include<bits/stdc++.h>
#include"rts.h"
using namespace std;
const int N=3e5+10;
const double alpha=0.74;
int n,id[N];
bool col[N];
inline void sp()
{
int i,j,x,v,l=1,r=1;
for(int i=1;i<n;++i) if(!col[id[i]]){
x=id[i];v=explore(l,x);
if(!col[v]){
for(;;v=explore(l,x)){
col[(l=v)]=true;
if(v==x) break;
}
}else{
for(;;){
v=explore(r,x);
col[(r=v)]=true;
if(v==x) break;
}
}
}
}
int rt=1,root,siz[N],sz[N],mx[N],dr[N],F[N],bel[N];
int head[N],to[N<<1],nxt[N<<1],tot,BN,S,MN;
bool cn[N];
map<int,int>g[N];
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
//_____DFZ
void fdrt(int x,int fr)
{
int i,j;sz[x]=1;mx[x]=0;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(j==fr || (!cn[j])) continue;
fdrt(j,x);sz[x]+=sz[j];mx[x]=max(mx[x],sz[j]);
}
mx[x]=max(mx[x],S-sz[x]);
if(mx[x]<MN) MN=mx[x],root=x;
}
void divide(int x)
{
int i,j,sum=S;siz[x]=S;cn[x]=false;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(!cn[j]) continue;
S=sz[j]<sz[x]?sz[j]:(sum-sz[x]);MN=N;
fdrt(j,0);F[root]=x;bel[root]=j;
g[x][j]=root;divide(root);
}
}
//OPERATION
void clr(int x)
{
if(!x) return;cn[x]=true;
for(map<int,int>::iterator it=g[x].begin();it!=g[x].end();++it)
clr(it->second);
g[x].clear();
}
void ins(int x)
{
int nw,v;
for(nw=rt;;){
v=explore(nw,x);
if(!col[v]){
col[v]=true;g[nw][v]=bel[v]=v;
F[v]=nw;lk(nw,v);lk(v,nw);siz[v]=1;
break;
}nw=g[nw][v];
}
for(BN=0;v^rt;v=F[v]){
siz[F[v]]++;
if(siz[F[v]]*alpha<=siz[v]) BN=F[v];
}
if(BN){
clr(BN);S=siz[BN];MN=N;fdrt(BN,0);
if(BN==rt) rt=root;else g[F[BN]][bel[BN]]=root;
F[root]=F[BN];bel[root]=bel[BN];
divide(root);
}
}
void play(int nn,int T,int dataType)
{
srand(173222);
col[1]=true;n=nn;
for(int i=1;i<n;++i) id[i]=i+1;
random_shuffle(id+1,id+n);
if(dataType==3) sp();
else{
for(int i=1;i<n;++i)
for(;!col[id[i]];ins(id[i]));
}
}