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 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥...