BZOJ 3083 遙遠的國度 樹鏈剖分

2021-06-26 16:28:44 字數 1760 閱讀 3356

題目大意:給出一顆無根樹,有鏈的修改操作,還有子樹的查詢。除此之外,還有選定這棵樹的乙個點為根。

思路:子樹操作,鏈上修改,帶size域的樹鏈剖分就可以搞定。換根肯定不能真的換,出題人要是閒的沒事所有操作都在換根就慘。我們可以畫一張圖模擬下換根。先按照讀入的順序建一顆有根樹,然後觀察當前的根在要詢問的點的位置。如果當前的根在要詢問的點的兒子中,那麼那個點為根的時候,當前點的子樹就是除了當前點的有根節點的子樹的點意外的所有點。如果根不在當前點的子樹中,那麼當前點的子樹不變。還有一種情況要特殊討論一下,當前點就是根,那麼子樹就是整棵樹。

ps:乙個點的子樹的範圍是pos[x]~pos[x] + size[x] - 1

code:

#include #include #include #include #define max 100010

#define inf 0x3f3f3f3f

#define left (pos << 1)

#define right (pos << 1|1)

using namespace std;

struct segmenttreetree[max << 2];

int points,asks;

int head[max],total;

int next[max << 1],aim[max << 1];

int deep[max],father[max],size[max],son[max];

int pos[max],top[max],cnt;

int capital;

inline void add(int x,int y)

void predfs(int x,int last)

}void dfs(int x,int last,int _top)

}inline bool insontree(int x,int f)

inline void pushdown(int pos)

}void modify(int l,int r,int x,int y,int pos,int c)

pushdown(pos);

int mid = (l + r) >> 1;

if(y <= mid) modify(l,mid,x,y,left,c);

else if(x > mid) modify(mid + 1,r,x,y,right,c);

else

tree[pos]._min = min(tree[left]._min,tree[right]._min);

}inline void modify(int x,int y,int c)

if(deep[x] < deep[y]) swap(x,y);

modify(1,cnt,pos[y],pos[x],1,c);

}int ask(int l,int r,int x,int y,int pos)

int main()

predfs(1,0);

dfs(1,0,1);

for(int x,i = 1; i <= cnt; ++i)

cin >> capital;

for(int flag,i = 1; i <= asks; ++i)

if(flag == 3)

if(son)

else printf("%d\n",ask(1,cnt,pos[x],pos[x] + size[x] - 1,1));

}} }

return 0;

}

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...