POJ3237 樹的維護

2022-05-08 04:36:12 字數 2757 閱讀 5233

給你由n個結點組成的樹。樹的節點被編號為1到n,邊被編號為1到n-1。每一條邊有乙個權值。然後你要在樹上執行一系列指令。指令可以是如下三種之一:

change i v:將第i條邊的權值改成v。

negate a b:將點a到點b路徑上所有邊的權值變成其相反數。

query a b:找出點a到點b路徑上各邊的最大權值。

第一行有乙個整數n(n<=10000)。

接下來n-1行每行有三個整數a,b,c,代表點a和點b之間有一條權值為c的邊。這些邊按照其編號從小到大給出。

接下來是若干條指令(不超過10^5條),都按照上面所說的格式。

最後一行是"done".

對每個「query」指令,輸出一行,即路徑上各邊的最大權值。

3 1 2 1

2 3 2

query 1 2

change 1 3

query 1 2

done

1 3lazy

陣列。

1 #include

2 #include3 #include4 #include5 #include6 #include7 #include

8 #include9 #include10 #include11 #include12 #include13 #include14

#define maxn 10010

15#define ls o*2

16#define rs o*2+1

17#define mi int mid=(l+r)>>1

18using

namespace

std;

19struct

datae[maxn*2

];22

char s[10

];23

int head[maxn],edge=0

,n;24

inttop[maxn],dis[maxn],dad[maxn],son[maxn],size[maxn],dfn[maxn],dfp[maxn],deep[maxn];

25int b[maxn*4],b1[maxn*4],lazy[maxn*4

];26

void dfs1(int x,int

fa)38}39

int de=0;40

void dfs2(int x,int

fa)50}51

void add(int

from,int to,int

w)57

void build(int o,int l,int

r)59

mi;60 build(ls,l,mid);build(rs,mid+1

,r);

61 b[o]=min(b[ls],b[rs]);

62 b1[o]=max(b1[ls],b1[rs]);63}

64void down(int

o)69

if(lazy[o]==-1

)73 lazy[ls]*=lazy[o],lazy[rs]*=lazy[o];

74 lazy[o]=1;75

}76int query(int o,int l,int r,int u,int

v)85

int lca(int x,int

y)91

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

92if(x!=y)

93 ans=max(ans,query(1,1,n,dfn[x]+1

,dfn[y]));

94return

ans;95}

96void negatee(int o,int l,int r,int u,int

v)104

mi;105

if(v<=mid) negatee(ls,l,mid,u,v);

106else

if(u>mid) negatee(rs,mid+1

,r,u,v);

107else negatee(ls,l,mid,u,mid),negatee(rs,mid+1,r,mid+1

,v);

108 b[o]=min(b[ls],b[rs]);

109 b1[o]=max(b1[ls],b1[rs]);

110}

111void lca1(int x,int

y)116

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

117if(x!=y)

118 negatee(1,1,n,dfn[x]+1

,dfn[y]);

119}

120void change(int o,int l,int r,int k,int

p)123

mi;124

if(k<=mid)change(ls,l,mid,k,p);

125else change(rs,mid+1

,r,k,p);

126 b[o]=min(b[ls],b[rs]);

127 b1[o]=max(b1[ls],b1[rs]);

128}

129int

main()

130147

if(s[0]=='c'

)155

if(s[0]=='n'

)160

}161

return0;

162 }

poj 3237 樹鏈剖分

對樹有三種操作 q a b 詢問a b路徑的最大值 n a b 對a b路徑上的數進行取反操作 a a c a b 將第a條邊的值改為b 對於取反操作,記錄區間的最大和最小值和標記k,更新線段即可。pragma comment linker,stack 1024000000,1024000000 i...

POJ 3237(樹鏈剖分)

這道題算是樹鏈剖分的模板題吧 其實也是我過的第一道樹鏈剖分的題目 歷盡千辛萬苦,終於把兩百多行的 敲出來了,ac的一瞬間還是挺爽的。在學會了樹鏈剖分之後,這道題不算很難的了,主要是在區間取反的部分注意一下細節。樹鏈剖分 挺長的,很多地方都是容易寫錯。我也是通過討論區的acmer給出的資料找出一些錯誤...

poj3237 樹鏈剖分

wa了n發,每次取相反數的時候,都需要交換最大值和最小值,這樣才能維護動態的平衡,因為lazy標誌的原因,取相反數,沒有更新到底,所以如果只維護乙個最大值會出問題。include include include const int n 50010 using namespace std struct...