bzoj2157 旅遊 樹鏈剖分 線段樹

2022-05-20 18:12:06 字數 3120 閱讀 5013

題目描述

ray 樂忠於旅遊,這次他來到了t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說, t 城中只有n − 1 座橋。ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥濘,令人煩躁。於是,他給每座橋定義乙個愉悅度w,也就是說,ray 經過這座橋會增加w 的愉悅度,這或許是正的也可能是負的。有時,ray 看待同一座橋的心情也會發生改變。現在,ray 想讓你幫他計算從u 景點到v 景點能獲得的總愉悅度。有時,他還想知道某段路上最美麗的橋所提供的最大愉悅度,或是某段路上最糟糕的一座橋提供的最低愉悅度。

輸入輸入的第一行包含乙個整數n,表示t 城中的景點個數。景點編號為 0...n − 1。接下來n − 1 行,每行三個整數u、v 和w,表示有一條u 到v,使 ray 愉悅度增加w 的橋。橋的編號為1...n − 1。|w| <= 1000。輸入的第n + 1 行包含乙個整數m,表示ray 的運算元目。接下來有m 行,每行描述了乙個操作,操作有如下五種形式: c i w,表示ray 對於經過第i 座橋的愉悅度變成了w。 n u v,表示ray 對於經過景點u 到v 的路徑上的每一座橋的愉悅度都變成原來的相反數。 sum u v,表示詢問從景點u 到v 所獲得的總愉悅度。 max u v,表示詢問從景點u 到v 的路徑上的所有橋中某一座橋所提供的最大愉悅度。 min u v,表示詢問從景點u 到v 的路徑上的所有橋中某一座橋所提供的最小愉悅度。測試資料保證,任意時刻,ray 對於經過每一座橋的愉悅度的絕對值小於等於1000。

輸出對於每乙個詢問(操作s、max 和min),輸出答案。

樣例輸入

30 1 1

1 2 2

8sum 0 2

max 0 2

n 0 1

sum 0 2

min 0 2

c 1 3

sum 0 2

max 0 2

樣例輸出32

1-153

題解樹鏈剖分+線段樹模板題,**量巨大

由於題目中給的是邊權,所以要把邊權加到深度大的節點的點權上。查詢時,注意要避免加上lca的點權。

修改時,sum取相反數,max和min互換後各自取相反數。

乙個minn寫成maxn調了1個半小時qaq

#include #include #define n 20010

#define lson l , mid , x << 1

#define rson mid + 1 , r , x << 1 | 1

using namespace std;

int x[n] , y[n] , z[n] , head[n] , to[n << 1] , val[n << 1] , next[n << 1] , cnt;

int fa[n] , w[n] , deep[n] , bl[n] , si[n] , pos[n] , tot;

int v[n] , sum[n << 2] , maxn[n << 2] , minn[n << 2] , tag[n << 2] , n;

char str[10];

void add(int x , int y , int z)

void dfs1(int x)

void dfs2(int x , int c)

}void pushup(int x)

void pushdown(int x)

}void build(int l , int r , int x)

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

build(lson) , build(rson);

pushup(x);

}void change(int p , int a , int l , int r , int x)

pushdown(x);

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

if(p <= mid) change(p , a , lson);

else change(p , a , rson);

pushup(x);

}void update(int b , int e , int l , int r , int x)

pushdown(x);

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

if(b <= mid) update(b , e , lson);

if(e > mid) update(b , e , rson);

pushup(x);

}int querysum(int b , int e , int l , int r , int x)

int querymax(int b , int e , int l , int r , int x)

int querymin(int b , int e , int l , int r , int x)

void solveupdate(int x , int y)

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

if(x != y) update(pos[x] + 1 , pos[y] , 1 , n , 1);

}int solvesum(int x , int y)

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

if(x != y) ans += querysum(pos[x] + 1 , pos[y] , 1 , n , 1);

return ans;

}int solvemax(int x , int y)

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

if(x != y) ans = max(ans , querymax(pos[x] + 1 , pos[y] , 1 , n , 1));

return ans;

}int solvemin(int x , int y)

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

if(x != y) ans = min(ans , querymin(pos[x] + 1 , pos[y] , 1 , n , 1));

return ans;

}int main()

} return 0;

}

BZOJ2157旅遊 樹鏈剖分 線段樹

ray 樂忠於旅遊,這次他來到了t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說,t 城中只有n 1 座橋。ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥...

BZOJ2157 旅遊 樹鏈剖分 線段樹

在對樹中資料進行改動的時候需要很多pushdown 具體操作見 不然會wa,大概原因和線段樹區間修改需要很多pushup是一樣的。這個輕重鏈的方法特別好用,雖然第一次寫樹鏈剖分但是容易理解又有優秀複雜度的結構讓人情不自禁orz。後來發現很久以前學lca的時候就學了樹鏈剖分只不過忘了,mdzz 因為忘...

BZOJ 2157 旅遊 樹鏈剖分

ray 樂忠於旅遊,這次他來到了t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說,t 城中只有n 1 座橋。ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥...