洛谷傳送門
ray 樂忠於旅遊,這次他來到了 t 城。t 城是乙個水上城市,一共有 nn 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說, t 城中只有 n-1n−1 座橋。
ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥濘,令人煩躁。於是,他給每座橋定義乙個愉悅度 ww,也就是說,ray 經過這座橋會增加 ww 的愉悅度,這或許是正的也可能是負的。有時,ray 看待同一座橋的心情也會發生改變。
現在,ray 想讓你幫他計算從 uu 景點到 vv 景點能獲得的總愉悅度。有時,他還想知道某段路上最美麗的橋所提供的最大愉悅度,或是某段路上最糟糕的一座橋提供的最低愉悅度。
給定一棵 nn 個節點的樹,邊帶權,編號 0 \sim n-10∼n−1,需要支援五種操作:
保證任意時刻所有邊的權值都在 [-1000,1000][−1000,1000] 內。
第一行乙個正整數 nn,表示節點個數。
接下來 n-1n−1 行,每行三個整數 u,v,wu,v,w,表示 u,vu,v 之間有一條權值為 ww 的邊,描述這棵樹。
然後一行乙個正整數 mm,表示運算元。
接下來 mm 行,每行表示乙個操作。
對於每乙個詢問操作,輸出一行乙個整數表示答案。
巨細節的一道題,並且,這道題的題解都是錯的(我的是對的)(我好錶臉)。
關於之前的題解(截止至2020.10.21之前)為什麼錯了,請見這個討論:
關於題解錯誤的一些看法
很明顯樹剖。
樹剖不會的走這邊:
**樹鏈剖分
首先要邊轉點,邊轉點的規則是把邊權轉到兒子節點上。這樣在鏈修改的時候,要刨除lca的點權。很好理解。
然後是取相反數的操作。維護乙個lazy標記,在打標記的時候容易發現的性質是:對於線段樹上的當前節點,新和就是和取反,新最大值是原最小值取反,新最小值是原最大值取反。
那麼這道題的思維部分就完事了,無腦開碼即可。
注意幾個蒟蒻曾經錯過的細節:
首先,刨除lca點權時,要判斷x,y是否在乙個點上,這時不需要刨,直接返回就行。
之後,lazy標記有沒有重複標記。這是指,對於乙個點,打兩次lazy標記等於沒打標記。這個可以通過異或運算來維護。
可以選擇使用結構體存線段樹,碼量會少很多。當然也可以像蒟蒻,寫很多函式來維護三個不同值,效果是一樣的。
附上5k**:
#include#include#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int maxn=2*1e5+10;
const int inf=1e9;
int n,m;
int tot,head[maxn],to[maxn<<1],nxt[maxn<<1],val[maxn<<1];
int cnt,son[maxn],top[maxn],id[maxn],deep[maxn],fa[maxn],size[maxn],a[maxn],w[maxn];
char opt[10];
int sum[maxn<<2],mx[maxn<<2],mn[maxn<<2];
int lazy[maxn<<2];
struct edge
idx[maxn];
int read()
void add(int x,int y,int z)
void dfs1(int x,int f)
}void dfs2(int x,int t)
}void pushup(int pos)
void build(int pos,int l,int r)
build(lson,l,mid);
build(rson,mid+1,r);
pushup(pos);
}void mark(int pos,int l,int r)
void pushdown(int pos,int l,int r)
}void update(int pos,int l,int r,int x,int k)
pushdown(pos,l,r);
if(x<=mid)
update(lson,l,mid,x,k);
else
update(rson,mid+1,r,x,k);
pushup(pos);
}void change(int pos,int l,int r,int x,int y)
pushdown(pos,l,r);
if(x<=mid)
change(lson,l,mid,x,y);
if(y>mid)
change(rson,mid+1,r,x,y);
pushup(pos);
}int query_sum(int pos,int l,int r,int x,int y)
int query_max(int pos,int l,int r,int x,int y)
int query_min(int pos,int l,int r,int x,int y)
void chain_upd(int x,int y)
else if(opt[1]=='n')
else if(opt[1]=='s')
else if(opt[1]=='m'&&opt[2]=='a')
else if(opt[1]=='m'&&opt[2]=='i')
}return 0;
}
P1505 國家集訓隊 旅遊
題目鏈結 這道題其實還是比較好想的,同樣是邊權問題。我們需要維護最大值,最小值,和。最坑的地方就是路徑上的所有數變相反數,其實這個就是把區間和 1,區間最大 1,區間最小 1,最後pushdown的時候將取反標記 1,接下來一系列都是常規操作。而這裡還要記住,單點修改時也要下傳lazy標記。而我在跳...
P1505 國家集訓隊 旅遊
ray 樂忠於旅遊,這次他來到了t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說,t 城中只有n 1 座橋。ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥...
洛谷 P1505 國家集訓隊 旅遊 解題報告
tt 樂忠於旅遊,這次他來到了 t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說,t 城中只有 n 1 座橋。tt 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥...