生活随笔
收集整理的這篇文章主要介紹了
BZOJ 4448 主席树+树链剖分(在线)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為什么題解都是離線的…… (抄都沒法抄)
搞一棵主席樹
1 操作 新樹上的當前節點設成1
2 操作 查max(i-xx-1,0)那棵樹上這條路徑上有多少個點是1
讓你找經過了多少個點 查的時候用deep 搞出來就好了
//By SiriusRen
using namespace std;
int n,
q,op,xx,yy,zz,first[N],v[N],
next[N],tot,root,rt[N],ans;
int size[N],fa[N],son[N],deep[N],top[N],change[N],back[N],cnt;
struct Tree{
int l,r,num;}tree[N
*30];
void Add(
int x,
int y){v[tot]=
y,
next[tot]=first[
x],first[
x]=tot++;}
void add(
int x,
int y){Add(
x,
y),Add(
y,
x);}
void dfs(
int x){size[
x]=
1;
for(
int i=first[
x];~i;i=
next[i])
if(v[i]!=fa[
x]){deep[v[i]]=deep[
x]+
1,fa[v[i]]=
x,dfs(v[i]);size[
x]+=size[v[i]];
if(size[son[
x]]<size[v[i]])son[
x]=v[i];}
}
void dfs2(
int x,
int tp){change[
x]=++cnt,back[cnt]=
x;top[
x]=tp;
if(son[
x])dfs2(son[
x],tp);
for(
int i=first[
x];~i;i=
next[i])
if(v[i]!=fa[
x]&&v[i]!=son[
x])dfs2(v[i],v[i]);
}
void push_up(
int pos){tree[
pos].num=tree[tree[
pos].l].num+tree[tree[
pos].r].num;}
int build(
int l,
int r){
int pos=++cnt;
if(l==r){
return pos;}
int mid=(l+r)>>
1;tree[
pos].l=build(l,mid),tree[
pos].r=build(mid+
1,r);
return pos;
}
int insert(
int o,
int l,
int r,
int num){
int pos=++cnt;tree[
pos]=tree[o];
if(l==r){tree[
pos].num=
1;
return pos;}
int mid=(l+r)>>
1;
if(mid>=num)tree[
pos].l=insert(tree[o].l,l,mid,num);
else tree[
pos].r=insert(tree[o].r,mid+
1,r,num);push_up(
pos);
return pos;
}
int query(
int o,
int l,
int r,
int L,
int R){
if(l>=L&&r<=R)
return tree[o].num;
int mid=(l+r)>>
1;
if(mid<L)
return query(tree[o].r,mid+
1,r,L,R);
else if(mid>=R)
return query(tree[o].l,l,mid,L,R);
else return query(tree[o].l,l,mid,L,R)+query(tree[o].r,mid+
1,r,L,R);
}
int find(
int x,
int y,
int wei){
int fx=top[
x],fy=top[
y],temp=
0;
while(fx!=fy){
if(deep[fx]<deep[fy])swap(
x,
y),swap(fx,fy);temp+=query(rt[wei],
1,n,change[fx],change[
x]),ans+=deep[
x]-deep[fx]+
1;
x=fa[fx],fx=top[
x];}
if(deep[
x]<deep[
y])swap(
x,
y);ans+=deep[
x]-deep[
y]+
1;
return temp+query(rt[wei],
1,n,change[
y],change[
x]);
}
int main(){mem(first,-
1);scanf(
"%d",&n);
for(
int i=
1;i<=n;i++){scanf(
"%d",&fa[i]);
if(!fa[i])root=i;
else add(i,fa[i]);}dfs(root),dfs2(root,root),cnt=
0,rt[
0]=build(
1,n);scanf(
"%d",&
q);
for(
int i=
1;i<=
q;i++){scanf(
"%d",&op);
if(op==
1){rt[i]=rt[i-
1],ans=
0;scanf(
"%d%d%d",&xx,&yy,&zz);zz=max(i-zz-
1,
0);
printf(
"%d %d\n",ans,find(xx,yy,zz));}
else scanf(
"%d",&xx),rt[i]=insert(rt[i-
1],
1,n,change[xx]);}
}
轉載于:https://www.cnblogs.com/SiriusRen/p/6532105.html
總結
以上是生活随笔為你收集整理的BZOJ 4448 主席树+树链剖分(在线)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。