BZOJ2157 旅遊 樹剖 或 LCT

2021-08-14 06:58:21 字數 4291 閱讀 6106

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),輸出答案。

0 1 1

1 2 2

sum 0 2

max 0 2

n 0 1

sum 0 2

min 0 2

c 1 3

sum 0 2

max 0 2

-1一共有10 個資料,對於第i (1 <= i <= 10) 個資料, n = m = i * 2000。

憑著對樹剖的熟練度,20min打完180+行直接1a【只會打板】

學了lct發現其實樹剖的題目都可以用lct刷刷

lct明天補上【如果我查得完錯】

update:已補lct

果然樹剖快挺多

#include

#include

#include

#include

#include

#define rep(i,n) for (int i = 1; i <= (n); i++)

#define redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)

#define ls (u << 1)

#define rs (u << 1 | 1)

using namespace std;

const

int maxn = 20005,maxm = 100005,inf = 1000000000;

inline

int rd()

while (c >= 48 && c <= 57)

return out * flag;

}char opt[10];

int h[maxn],ne = 0,n,m;

struct edgeed[maxm];

inline

void build(int u,int v,int w,int i); h[u] = ne++;

ed[ne] = (edge); h[v] = ne++;

}int fa[maxn],dep[maxn],son[maxn],v[maxn],id[maxn],p[maxn],h[maxn],top[maxn],siz[maxn];

int cnt = 0;

void dfs1(int u)

}void dfs2(int u,int flag)

int sum[4 * maxn],mx[4 * maxn],mn[4 * maxn],tag[4 * maxn],l,r;

void pup(int u)

void pd(int u)

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

int mid = l + r >> 1;

build(ls,l,mid);

build(rs,mid + 1,r);

pup(u);

}void modify(int u,int l,int r,int v)

pd(u);

int mid = l + r >> 1;

if (mid >= l) modify(ls,l,mid,v);

else modify(rs,mid + 1,r,v);

pup(u);

}void rever(int u,int l,int r)

pd(u);

int mid = l + r >> 1;

if (mid >= l) rever(ls,l,mid);

if (mid < r) rever(rs,mid + 1,r);

pup(u);

}int query(int u,int l,int r)

int qmin(int u,int l,int r)

int qmax(int u,int l,int r)

void solve1()

void solve2()

if (u == v) return;

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

l = id[u] + 1; r = id[v];

rever(1,1,n);

}void solve3()

if (u != v)

printf("%d\n",ans);

}void solve4()

if (u != v)

printf("%d\n",ans);

}void solve5()

if (u != v)

printf("%d\n",ans);

}int main()

return

0;}

lct:【**短但會慢一點】

#include

#include

#include

#include

#include

#define isrt(u) (!f[u] || (ch[f[u]][0] != u && ch[f[u]][1] != u))

#define isr(u) (ch[f[u]][1] == u)

#define rep(i,n) for (int i = 1; i <= (n); i++)

#define redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)

#define ls (ch[u][0])

#define rs (ch[u][1])

using

namespace

std;

const

int maxn = 40005,maxm = 100005,inf = 1000000000;

inline

int rd()

while (c >= 48 && c <= 57)

return out * flag;

}int rev[maxn],min[maxn],max[maxn],f[maxn],ch[maxn][2],sum[maxn];

int tag[maxn],v[maxn],n,m,ed[maxn];

char opt[10];

void rever(int u)

void pup(int u)

void pd(int u)

if (tag[u])

}void push_down(int u)

void spin(int u)

void splay(int u)

void access(int u)

void make_rt(int u)

void split(int u,int v)

void link(int u,int v)

void solve1()

void solve2()

void solve3()

void solve4()

void solve5()

int main()

m = rd();

while (m--)

return

0;}

BZOJ2157 旅遊 樹剖 或 LCT

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

BZOJ 2157 旅遊 樹剖 線段樹

題目傳送門 題目分析 似乎是個裸題。把邊權放到深度大的那個點上,查詢的時候去掉lca就好了。然而我雖然知道這一點打的時候仍然把lca加進去了。然後就是瘋狂複製貼上再ctrlf替換。然而還是wa。寫的時候c操作改點的時候沒有用dfs序直接把點編號帶了進去。後來又發現連邊的時候連了兩條u i v i 自...

BZOJ 2157 旅遊 樹鏈剖分

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