【題目描述】
描述多年前 lyra 在 evan 的壁爐裡發現了一棵樹,這棵樹非常奇特,它貼著壁爐的內壁生長,汲取火焰中的魔法元素給自己提供養分,善於記憶的 lyra 記下了當時樹的形態。
當年年幼無知的 lyra 還不知道 evan 家這棵樹具有靈性,繼續生長下去有著無盡的潛力和價值。如今 lyra 又站在 evan 的壁爐旁,發現 evan 家的這棵樹已經長了不少,作為 lyra 的好朋友, evan 告訴 lyra,這棵靈樹生長需要 evan 投入魔法石到火焰中,而它生長過程也十分奇特:
這棵樹可以抽象成一棵帶邊權的有根樹,由於生長在牆壁上,每個節點的所有孩子節點之間是有相對順序的(可以假設為從左至右),此外樹還有兩個屬性 c1,c2,樹的生長包含四種變化:
生長: 對於樹的乙個節點 x,考慮其孩⼦節點 y1,y2,⋯,ym,從 x 上長出乙個新節點 z 插入到其孩子中第 k 個位置,於是 x 的孩子節點序列變成了 y1,y2,⋯,yk−1,z,yk,yk+1⋯,ym。 將 的權值設為 w 的消耗為 c1w 單位魔法石。
伸展: 對於樹的乙個節點 x,考慮其孩子節點 y1,y2,⋯,ym,選取乙個區間 [l,r](1≤l≤r≤m),從 x 上長出乙個新節點 z 作為 yl,yl+1,⋯,yr 的父親。此時 x 的孩子序列為y1,y2,⋯,yl−1,z,yr+1,⋯,ym, z 的孩子序列為 yl,yl+1,⋯,yr。並且對於 l≤i≤r,邊 就是原樹上的邊 。將 的權值設為 w 的消耗為 c1w 單位魔法石。
收縮: 對於樹的乙個節點 x,考慮其孩子節點 y1,y2,⋯,ym,選取其乙個孩子節點 yk,令其孩子序列為 z1,z2,⋯,zp,將 縮掉(即去掉 yk,並將 yk 的所有孩子保持順序接到yk 原來在 x 孩子中的位置)。此時 x 的孩子序列為 y1,y2,⋯,yk−1,z1,z2,⋯,zp,yk+1,⋯,ym。並且對於 1≤i≤p,邊 就是原樹上的邊 。令 w 等於原樹上 的權值,則此操作需要消耗 c1w 單位魔法石。
轉化: 對於樹上乙個節點 x 和其某個孩子 y,保持 y 在 x 的孩子序列中位置不變,把的權值從 w1(現有權值)修改為 w2,需要消耗 c2∣w1−w2∣ 單位的魔法石。
注意:第四種操作使用的魔法與前三種操作有所不同,所以由操作「生長」和「伸展」生成的邊無法繼續參與「轉化」,同時「轉化」過的邊無法被「收縮」。
lyra 知道魔法石是一種貴重的資源,很少有人能這樣燒著玩,為了弄清楚 evan 究竟有多富有,她想通過樹的形態變化來確定這些年 evan 至少花費了多少魔法石。
現在給出 lyra 小時候樹的形態與邊權,和現在樹的形態與邊權,求由如上四個操作把樹做如此變化的最小消耗。
兩棵樹被認為是相同當且僅當存在乙個編號的對映,使得在該對映下一棵樹與另一棵樹的邊,每個節點的孩子順序,以及對應邊權都完全相同,且根保持不變。
n
1<=50
,n
2<
=2000
n_1<=50,n_2<=2000
n1<=5
0,n2
<=2
000毒瘤題。注意到生長伸展和收縮互為逆操作,我們可以把在一棵樹上生長伸展和收縮,等價地變為在兩棵樹上同時收縮。暴力即2
n2^n
2n列舉每條邊是否收縮。考慮括號序列,那麼收縮意味著刪除一對括號,轉化意味著改變一對括號的權值,那麼問題轉化成了給定兩個括號序列,問使這兩個括號序列匹配的最小代價。定義fl,
r,x,
yf_
fl,r,x
,y表示第一棵樹的括號序列的區間[l,r]和第二顆樹的區間[x,y]匹配的最小代價。一對括號沒有被刪除當且僅當左右括號都沒有被刪除。所以轉移時我們可以從左到右考慮每個左括號,跳過右括號(右括號所在括號對已被刪除)。轉移時考慮三種情況:1.刪除第一棵樹的左括號。2.刪除第二顆樹的左括號。3.通過轉化使兩個左括號匹配。時間複雜度o(n
12n2
2)
o(n_1^2n_2^2)
o(n12
n22
)。考慮優化,對於一段正在考慮的區間,括號序列形如:
( ..
.)(.
..).
..(.
..)(
...)
(...)(...)...(...)(...)
(...)(
...)
...(
...)
(...
)為了盡量避開第二顆樹的重兒子,我們可以比較最左端括號和最右端括號的大小,只考慮刪除小一點的那個括號的左(右)括號。轉移時跳過另一半已被刪除的左右括號即可。可以證明,第二顆樹的轉移時間複雜度為o(∑
size
輕兒子)
=o(n
2log
n2
)o(\sum size_)=o(n_2logn_2)
o(∑siz
e輕兒子
)=o
(n2
logn
2),第一棵樹轉移時間複雜度o(n
12
)o(n_1^2)
o(n12
)。總時間複雜度為o(n
12n2
logn
2)
o(n_1^2n_2logn_2)
o(n12
n2l
ogn2
)
#include
#define re register
using
namespace std;
const
int n=
1e5+
5,mod=
19260817
;inline
intred()
typedef
long
long ll;
int n[2]
,a,b;ll c1,c2;
ll g[mod]
,vis[mod]
;struct nodee[2]
[n];
int f[2]
[n],nxp[2]
[n],cnt[2]
,d[2
][n]
,st[2]
[n],ed[2]
[n],tot[2]
;const ll h1=
103*
103,h2=
103*
103*
4003
;inline ll hash
(const
int&l,
const
int&r,
const
int&x,
const
int&y)
inline
intfind
(int l,
int r,
int x,
int y)
inline
void
add(
const
int&u,
const
int&v,
const
int&w,
const
int&t)
;nxp[t]
[cnt[t]
]=f[t]
[u];f[t]
[u]=cnt[t];}
void
dfs(
int u,
const
int&t)
}void
init
(const
int&t)
int*d1=d[0]
,*st1=st[0]
,*ed1=ed[0]
;int
*d2=d[1]
,*st2=st[1]
,*ed2=ed[1]
;node*e1=e[0]
,*e2=e[1]
;inline
void
cmin
(ll&x,
const ll&y)
ll dp
(int l,
int r,
int x,
int y)
if(ed2[d2[x]
]-st2[d2[x]
]<=ed2[d2[y]
]-st2[d2[y]])
else
}signed
main()
括號序列(棧)
定義滿足以下規則字串為規則序列,否則不是規則序列 1 空序列是規則序列 2 如果s是規則序列,那麼 s s 和也是規則序列 3 如果a和b都是規則序列,那麼ab也是規則序列。例如,下面的字串都是規則序列 而以下幾個則不是 現在,給你一些由 構成的字串,請判斷該字串是否為規則序列。第一行 乙個正整數n...
合法括號序列
合法括號序列 鍵盤上有左括號 右括號 和退格鍵 共三個鍵。牛牛希望按鍵n次,使得輸入的字串恰好乙個合法的括號序列。每按一次左括號 字串末尾追加乙個左括號 每按一次右括號 字串末尾追加乙個右括號 每按一次退格鍵 會刪掉字串的最後乙個字元,特別的,如果字串為空,牛牛也可以按退格,但是什麼都不會發生。輸出...
2058 括號序列
時間限制 2 s 空間限制 128000 kb 題目等級 silver 題解檢視執行結果 description 定義滿足以下規則字串為規則序列,否則不是規則序列 1 空序列是規則序列 2 如果s是規則序列,那麼 s s 和也是規則序列 3 如果a和b都是規則序列,那麼ab也是規則序列。例如,下面的...