bzoj3083 遙遠的國度(樹鏈剖分 線段樹)

2022-02-28 03:48:20 字數 3340 閱讀 6123

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的操作,輸出一行代表對應子樹的最小點權值。

輸入樣例#1: 複製

3 7

1 21 3

1 2 3

13 1

2 1 1 6

3 12 2 2 5

3 12 3 3 4

3 1

輸出樣例#1: 複製

123

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。

題解

第一眼看過去覺得是lct

然後發現沒法維護子樹資訊,決定每乙個點開一棵平衡樹,後來發現空間要爆……

於是好好學了一下正解

首先查詢和修改路徑都是樹剖的基本操作這裡不提

然後現在最重要的是換根操作咋整

我們考慮一下,當前根與點$x$在原樹中的關係無非以下幾種:

1.當前根就是點$x$——那麼直接輸出整棵樹答案就行了

2.當前根在原樹中不在$x$的子樹內——那麼哪怕根換成了現在的根,$x$的子樹還是沒有變化,那麼我們可以直接去原來的子樹裡查詢

3.當前根在原樹中在$x$的子樹內——那麼我們設當前根在$u$點的子樹$v$內,那麼所要求的答案就是整棵樹除去$v$這一棵子樹的答案。至於怎麼求$v$,可以從$root$往上跳重鏈,直到跳到$u$為止,那麼就是看它從哪乙個$u$點的子節點跳過來的就好了

因為讀入進來的時候路徑端點和更改的值弄錯了……而且忘記找$v$了……調了半天

1

//minamoto

2 #include3 #include4

#define int unsigned int

5using

namespace

std;

6#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?eof:*p1++)

7char buf[1

<<21],*p1=buf,*p2=buf;

8 templateinline bool cmin(t&a,const t&b)

9 inline int

read()

19char sr[1

<<21],z[30];int c=-1

,z;20 inline void ot()

21 inline void print(int

x)26

const

int n=100005,inf=0xffffffff;27

int head[n],next[n<<1],ver[n<<1

],tot;

28int

fa[n],dep[n],son[n],sz[n],top[n],ls[n],rs[n],cnt;

29int v[n],mn[n<<2],tag[n<<2

];30

intn,m,rt;

31 inline void add(int u,int

v)35

void dfs1(int

u)43}44

}45void dfs2(int u,int

t)53

}54 rs[u]=cnt;55}

56 inline void pushup(int p)

57 inline void pushdown(int

p)61

void build(int p,int l,int

r)67

void update(int p,int l,int r,int ql,int qr,int

x)75

int query(int p,int l,int r,int ql,int

qr)83

int find(int t,int

u)88

return

son[t];89}

90void modify(int u,int v,int

x)95

if(dep[u]>dep[v]) swap(u,v);

96 update(1,1

,n,ls[u],ls[v],x);97}

98signed main()

104 dfs1(1),dfs2(1,1

);105

for(int i=1;i<=n;++i) v[ls[i]]=read();

106 build(1,1

,n);

107 rt=read();

108while(m--)

122break

;123

}124

}125

}126

ot();

127return0;

128 }

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