維護一棵樹,支援換根,路徑修改,當前根下的子樹最小值。
首先可以發現換根沒什麼太大的用處,無論換了幾次,只有最後一次是對當前有影響的。所以記錄下現在哪個做根,樹的形態不用動。
第二種操作直接樹剖。
關鍵是查詢,因為換根,有點麻煩。
假設整棵樹一開始的根是1,那麼當x做根時,只對x到1的路徑上的點的子樹產生影響。
那麼其他點就直接dfs序化成區間求最值。
當乙個點y是x的祖宗,那麼它的子樹就變成這樣:
右上角為y的子樹。
所以找到y到x的路徑的第乙個點,除去這棵子樹其他就區間的最值就是答案。
code:
#include
#include
#include
#include
using namespace std;
struct trnodetr[200010];int ys[100010],z=0,tot=0,rt;
struct nodea[200010];int len=0,last[100010];
int n,m;
intread()
while(ch>='0'&&ch<='9')
return
x*f;
}void ins(int
x,int
y)void pre_node(int
x,int fa)
}void pre_edge(int
x,int top)
}int bt(int l,int r)
returnx;}
void update(int
x)void change(int
x,int l,int r,int fl,int fr,int c)
int mid=(l+r)/2;
if(tr[x].u!=0) update(x);
if(fr<=mid) change(tr[x].lc,l,mid,fl,fr,c);
else
if(fl>mid) change(tr[x].rc,mid+1,r,fl,fr,c);
else change(tr[x].lc,l,mid,fl,mid,c),change(tr[x].rc,mid+1,r,mid+1,fr,c);
tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
}int findans(int
x,int l,int r,int fl,int fr)
void solve(int
x,int
y,int c)
if(tr[x].dep
change(1,1,n,ys[y],ys[x],c);
}bool check(int
x,int
y)//判斷x是否為y的祖宗
void work(int
x) if(x==rt)
inty=rt,ty=tr[y].top,tx=tr[x].top;
while(ty!=tx&&tr[ty].fa!=x)
y=tr[ty].fa,ty=tr[y].top;
if(tx==ty) ty=tr[x].son;
int l=ys[ty],r=tr[ty].la;
int ans=(1
<<28);
if(l!=1) ans=min(ans,findans(1,1,n,1,l-1));
if(r!=n) ans=min(ans,findans(1,1,n,r+1,n));
printf("%d\n",ans);
}int main()
pre_node(1,0);pre_edge(1,1);
bt(1,n);
for(int i=1;i<=n;i++)
rt=read();
while(m--)
if(opt==3)}}
bzoj3083 遙遠的國度
題意 給定一棵樹,支援換根,路徑權值覆蓋,求子樹最小。思路 求子樹?上樹鏈剖分,但是換根怎麼辦?我們只能通過原有資訊推出換根後的答案。換根不影響路徑修改,所以只要考慮子樹最小值的維護。這裡要分3種情況討論 1 如果詢問點是當前根,直接返回整棵樹的最小值。2 如果在原樹中,當前根不在 x的子樹中,直接...
bzoj3083 遙遠的國度
time limit 10 sec memory limit 1280 mb submit 1733 solved 429 submit status discuss description 描述 zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的...
bzoj3083 遙遠的國度
time limit 10 sec memory limit 1280 mb submit 1960 solved 484 submit status discuss 描述zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神ra...