bzoj 4573: [Zjoi2016]大森林
阿新 • • 發佈:2018-04-28
操作 題解 ron 時間 acc 復雜 upd 並且 || 到 \(n\) 的公共部分我們一起考慮,不同的部分就直接新建節點
考慮維護添加,刪除操作的復雜度
我們每產生一個新的生長節點就新建一個虛點,然後把新長出來的都接上去
如果按加入時間考慮的話,有很多連續的節點都是同一個父親,所以我們用一個虛點暫時代替它們的父親
然後對於 \(1\) 到 \(n\) 的不同的樹,它們的父親是不一樣的,因為建立了這個虛點,所以只需要把虛點的父親變一下,就可以達到把所有的點的父親都改變的效果了
Description
小Y家裏有一個大森林,裏面有n棵樹,編號從1到n。一開始這些樹都只是樹苗,只有一個節點,標號為1。這些樹
都有一個特殊的節點,我們稱之為生長節點,這些節點有生長出子節點的能力。小Y掌握了一種魔法,能讓第l棵樹
到第r棵樹的生長節點長出一個子節點。同時她還能修改第l棵樹到第r棵樹的生長節點。她告訴了你她使用魔法的
記錄,你能不能管理她家的森林,並且回答她的詢問呢?
Solution
有點神仙,看了題解的做法
首先顯然要離線,否則空間都是錯的,這樣維護一棵樹就好了
然後發現都是區間修改,掃描線維護一下節點就好了
但是還有刪除節點這樣的操作,復雜度保證不了
不如先把樹的形態都建出來,對於 \(1\)
考慮維護添加,刪除操作的復雜度
我們每產生一個新的生長節點就新建一個虛點,然後把新長出來的都接上去
如果按加入時間考慮的話,有很多連續的節點都是同一個父親,所以我們用一個虛點暫時代替它們的父親
然後對於 \(1\) 到 \(n\) 的不同的樹,它們的父親是不一樣的,因為建立了這個虛點,所以只需要把虛點的父親變一下,就可以達到把所有的點的父親都改變的效果了
具體的也說不清楚,看代碼比較直觀.....
#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=4e5+10;
int n,m,ch[N][2],fa[N],a[N],w[N];
inline void upd(int x){w[x]=w[ch[x][0]]+w[ch[x][1]]+a[x];}
inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void rotate(int x){
int y=fa[x];bool t=ch[y][1]==x;
ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
ch[x][!t]=y;fa[x]=fa[y];
if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[y]=x;upd(y);upd(x);
}
inline void splay(int x){
while(!isrt(x)){
int y=fa[x],p=fa[y];
if(isrt(y))rotate(x);
else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
inline int access(int x){
int y=0;
while(x)splay(x),ch[x][1]=y,upd(x),x=fa[y=x];
return y;
}
inline void link(int x,int y){
access(x);splay(x);fa[x]=y;
}
inline void cut(int x){
access(x);splay(x);fa[ch[x][0]]=0;ch[x][0]=0;upd(x);
}
inline int query(int x,int y){
int ret=0,t;
access(x);splay(x);ret+=w[x];
t=access(y);splay(y);ret+=w[y];
access(t);splay(t);ret-=w[t]<<1;
return ret;
}
int L[N],R[N],id[N],cnt=2,ans[N],top=0;
struct data{
int ty,p,x,y;
inline bool operator <(const data &t)const{
if(p!=t.p)return p<t.p;
return ty<t.ty;
}
}q[N];
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>m;
int op,l,r,x,y=2,tp=0,ID=1;
L[1]=1;R[1]=n;id[1]=1;w[1]=a[1]=1;
L[2]=1;R[2]=n;w[2]=a[2]=0;link(2,1);
for(int i=1;i<=m;i++){
gi(op);gi(l);gi(r);
if(op==0){
a[++cnt]=1;w[cnt]=1;L[++ID]=l;R[ID]=r;id[ID]=cnt;
link(cnt,y);
}
else if(op==1){
gi(x);
a[++cnt]=0;w[cnt]=0;l=max(l,L[x]);r=min(r,R[x]);
if(l<=r){
link(cnt,y);
q[++top]=(data){-1,l,cnt,id[x]};
q[++top]=(data){-1,r+1,cnt,y};
y=cnt;
}
}
else gi(x),q[++top]=(data){++tp,l,id[r],id[x]};
}
sort(q+1,q+top+1);
for(int i=1,j=1;i<=n;i++){
while(j<=top && q[j].p==i){
if(q[j].ty==-1)cut(q[j].x),link(q[j].x,q[j].y);
else ans[q[j].ty]=query(q[j].x,q[j].y);
j++;
}
}
for(int i=1;i<=tp;i++)printf("%d\n",ans[i]);
return 0;
}
bzoj 4573: [Zjoi2016]大森林