BZOJ 3531(樹鏈剖分 線段樹)

2022-08-05 16:03:15 字數 2690 閱讀 6821

problem 旅行 (bzoj 3531)

題目大意

給定一顆樹,樹上的每個點有兩個權值(x,y)。   

要求維護4種操作:

操作1:更改某個點的權值x。

操作2:更改某個點的權值y。

操作3:求a-->b路徑上所有x屬性與a,b相同的點y屬性的和。

操作4:求a-->b路徑上所有x屬性與a,b相同的點y屬性的最大值。

n,q ,x <= 10^5  ,  y <= 10^4

解題分析

由於x屬性的範圍較大,無法直接統計。

考慮每次修改為單點修改,詢問時只對相同x屬性的詢問。

因此,對於每個x屬性開一棵線段樹,詢問時直接在相對應的線段樹內查詢。

開這麼多棵線段樹的話,就要動態開點,某個點的左右兒子的編號不是當前點編號的2倍或2倍加1。

參考程式

1 #include 2 #include 3 #include 4 #include 5

using

namespace

std;67

#define n 10000008

8#define v 100008

9#define e 200008

10#define lson l,m,ls[rt]

11#define rson m+1,r,rs[rt]

1213

intn,q,cnt;

14int

size[v],dep[v],fa[v],son[v],w[v],top[v],rk[v],root[v];

15int

a[v],c[v];

1617

struct

lineeg[e];

20int

lt[v],sum;

2122

void adt(int u,int

v)25

void add(int u,int

v)28

29struct

segment_tree

35void update(int x,int val,int l,int r,int &rt)

42int m=(l+r)/2;43

if (x <=m) update(x,val,lson);

44if (m

45pushup(rt);46}

47int query_sum(int l,int r,int l,int r,int

rt)51

int m=(l+r)/2;52

int res=0;53

if (l <= m) res+=query_sum(l,r,lson);

54if (m < r) res+=query_sum(l,r,rson);

55return

res; 56}

57int query_max(int l,int r,int l,int r,int

rt)61

int m=(l+r)/2;62

int res=0;63

if (l <= m) res=max(res,query_max(l,r,lson));

64if (m < r) res=max(res,query_max(l,r,rson));

65return

res; 66}

67}t;

6869

void dfs_1(int

u)79}80

void dfs_2(int u,int

tp) 88}

89void solve_sum(int x,int

y)96

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

97 res+=t.query_sum(w[x],w[y],1

,n,root[cl]);

98 printf("

%d\n

",res);99}

100void solve_max(int x,int

y)107

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

108 res=max(res,t.query_max(w[x],w[y],1

,n,root[cl]));

109 printf("

%d\n

",res);

110}

111112

intmain()

121 dfs_1(1

);122 dfs_2(1,1

);123 cnt=0

;124

for (int i=1;i<=n;i++) t.update(w[i],a[i],1

,n,root[c[i]]);

125while (q--)

134if (strcmp(x,"

cw")==0

)138

if (strcmp(x,"

qs")==0

)141

if (strcmp(x,"

qm")==0

)144

}145 }

view code

bzoj3531 樹刨 線段樹動態開點

題意 一棵樹,每個點有顏色,4種操作,1.單點修改權值 2.單點修改顏色 3.查詢路徑顏色相同的點權和 4.查詢路徑顏色相同的點權最大值。思路 樹刨 線段樹動態開點,開1e5個線段樹。include using namespace std define ll long long define for...

BZOJ 2243 樹鏈剖分 線段樹

include define n 101000 define frei freopen in.txt r stdin define freo freopen out.txt w stdout define mem a,b memset a,b,sizeof a define lson root 1 ...

BZOJ 4811 樹鏈剖分 線段樹

思路 感覺這題也可神了.還是我太弱 首先發現每一位不會互相影響,可以把每一位分開考慮,然後用樹鏈剖分或者lct維護這個樹 修改直接修改,詢問的時候算出來每一位填0,1經過這條鏈的變換之後得到的值 考慮貪心,從高往低,如果這一位填0可以得到1,那麼填0一定是最優的 否則如果可以填1,就把這一位填為1 ...