bzoj3083 遙遠的國度

2021-07-09 20:09:28 字數 2917 閱讀 5954

time limit: 10 sec  

memory limit: 1280 mb

submit: 1960  

solved: 484 [

submit][

status][

discuss]

描述zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神rapid阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。

問題是這樣的:遙遠的國度有n個城市,這些城市之間由一些路連線且這些城市構成了一顆樹。這個國度有乙個首都,我們可以把這個首都看做整棵樹的根,但遙遠的國度比較奇怪,首都是隨時有可能變為另外乙個城市的。遙遠的國度的每個城市有乙個防禦值,有些時候rapid會使得某兩個城市之間的路徑上的所有城市的防禦值都變為某個值。rapid想知道在某個時候,如果把首都看做整棵樹的根的話,那麼以某個城市為根的子樹的所有城市的防禦值最小是多少。由於rapid無法解決這個問題,所以他攔住了zcwwzdjn希望他能幫忙。但zcwwzdjn還要追殺sb的zhx,所以這個重大的問題就被轉交到了你的手上。

第1行兩個整數n m,代表城市個數和運算元。

第2行至第n行,每行兩個整數 u v,代表城市u和城市v之間有一條路。

第n+1行,有n個整數,代表所有點的初始防禦值。

第n+2行乙個整數 id,代表初始的首都為id。

第n+3行至第n+m+2行,首先有乙個整數opt,如果opt=1,接下來有乙個整數id,代表把首都修改為id;如果opt=2,接下來有三個整數p1 p2 v,代表將p1 p2路徑上的所有城市的防禦值修改為v;如果opt=3,接下來有乙個整數 id,代表詢問以城市id為根的子樹中的最小防禦值。

對於每個opt=3的操作,輸出一行代表對應子樹的最小點權值。

3 71 21 3

1 2 3

13 1

2 1 1 6

3 12 2 2 5

3 12 3 3 4

3 1123

4提示對於20%的資料,n<=1000 m<=1000。

對於另外10%的資料,n<=100000,m<=100000,保證修改為單點修改。

對於另外10%的資料,n<=100000,m<=100000,保證樹為一條鏈。

對於另外10%的資料,n<=100000,m<=100000,沒有修改首都的操作。

對於100%的資料,n<=100000,m<=100000,0《所有權值<=2^31。

zhonghaoxi提供

要求維護鏈上修改、子樹查詢和換根操作。

樹鏈剖分本質就是一種dfs序,所以子樹查詢可以轉化為區間查詢,用線段樹維護即可。

而換根操作只需要記錄當前根節點的序號,每次查詢時判斷根和查詢節點的位置關係即可。(詳見bzoj3306 樹)

這道題調了一下午,wa了無數次,原因是**第149行t的賦值寫成了t=d[rt]-d[x]……

#include#include#include#include#include#include#define f(i,j,n) for(int i=j;i<=n;i++)

#define d(i,j,n) for(int i=j;i>=n;i--)

#define ll long long

#define maxn 100005

#define inf 1000000000

using namespace std;

struct edge_type

e[maxn*2];

struct seg

t[maxn*4];

int n,m,cnt,tot,x,y,z,rt,opt;

int head[maxn],sz[maxn],w[maxn],d[maxn],son[maxn];

int belong[maxn],f[maxn],fa[maxn][20],l[maxn],r[maxn];

bool vst[maxn];

inline int read()

while (ch>='0'&&ch<='9')

return x*f;

}inline void add_edge(int x,int y)

;head[x]=cnt;

e[++cnt]=(edge_type);head[y]=cnt;

}inline void dfs1(int x)

}inline void dfs2(int x,int chain)

inline int lca(int x,int y)

inline void change(int k,int l,int r,int x)

int mid=(t[k].l+t[k].r)>>1;

pushdown(k);

if (r<=mid) change(k<<1,l,r,x);

else if (l>mid) change(k<<1|1,l,r,x);

else

pushup(k);

}inline int query(int k,int l,int r)

inline void solvecover(int x,int f,int z)

change(1,l[f],l[x],z);

}int main()

f(i,1,n) w[i]=read();

rt=read();

dfs1(rt);dfs2(rt,rt);

build(1,1,n);

f(i,1,m)

else

{ x=read();

if (x==rt) printf("%d\n",t[1].mn);

else

{int f=lca(x,rt);

if (x==f)

{int t=d[rt]-d[x]-1,ans=inf;y=rt;

f(i,0,19) if ((1<

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 遙遠的國度

給定一棵有根樹,支援3種操作 1.把首都修改為id 2.將p1 p2路徑上的所有城市的防禦值修改為v 3.詢問以城市id為根的子樹中的最小防禦值。畫了一堆圖之後終於搞懂了一點點,首先換根的話肯定不是真的換。對於每次詢問,設現在的根為root,準備詢問的結點為x。來考慮幾種情況。1.root x 詢問...