洛谷 P1505 國家集訓隊 旅遊

2022-03-20 02:34:35 字數 2770 閱讀 9645

洛谷傳送門

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