題目鏈結
首先吐槽一波原題意,描述地太不清楚了,還是出題人想要出語文斷句題?
題目鏈結是團隊考試的題,題意重置版。
顯然我們要避免那種$i*i$的情況,因為這樣非常不划算,($i^2>=i>i-j$)。那我們來看看能不能安排乙個合法的順序來規避這個情況。顯然是可以的,因為如果我們按照字尾關係連邊,它會形成乙個$dag$,不可能產生衝突,我們的安排只要符合這個$dag$的遞推關係就可以規避$i*i$的情況。
在這裡,沒有字尾的情況可以視為字尾是空串,這樣就可以把所有情況統一起來,接下來我們就只討論剩下的這一種情況。
既然是要符合$dag$所表示的關係,那麼對於乙個單詞$i$,我們把單詞$i$和他的最長字尾$j$連邊,由於乙個單詞的最長字尾是唯一確定的,而乙個單詞可以同時是很多個單詞的字尾,所以他們的關係大概是長這個樣子的:
但是這東西看起來很彆扭,我們可以改一改,反轉一下邊,就非常優美了:
如果反過來的話,就相當於父親是兒子的最長字尾。對於乙個單詞的記憶時間,就是它自己被記憶的順序號減去自己的父親被記憶的順序號,即父子被訪問的時間間隔差。
相當於我們要給這棵樹確定乙個訪問節點的順序,乙個點只有在他的父親被訪問之後才能被訪問,而且訪問順序不一定要按照$dfs$的順序來,可以跳著訪問,比如$u$的四個兒子:$v1$,$v2$,$v3$,$v4$,我可以挨著訪問$v1$,$v2$,$v3$,$v4$,然後再去訪問$v1$的兒子。但是這樣卻一定沒有按照$dfs$的順序優,因為$v1$,$v2$,$v3$的兒子們和它的父親(也就是$v1$,$v2$,$v3$)之間相隔的時間變長了。
所以按照$dfs$的順序訪問最優。而兄弟之間的訪問順序,則應該讓子樹大小比較小的兒子先遍歷會更優,因為在選擇兄弟之間的順序時,他們的父親已經被訪問,也就是父親的訪問時間已經確定,選子樹小的可以使它的兄弟們的更大的子樹等待的時間更少(模擬排隊接水的那個貪心)。
那麼現在最關鍵的問題就是怎麼求出我們上面的那棵樹,這棵樹父親是兒子的最長字尾,如果把串反過來(就變成了父親是兒子的最長字首)只需要一棵$trie$,把相鄰的單詞節點連邊就可以解決了。
**非常小巧清新。
1 #include2 #include3 #include4 #include5codeusing
namespace
std;
6#define n 100000
7#define m 510000
8#define inf 0x3f3f3f3f
9#define mod 1000000007
10#define ll long long
11int
rd()
1215
while(c>='
0'&&c<='9')
16return f*x;17}
18char
s[m];
19int ch[m][26
],cnt,ed[m];
20 vectorg[m];
21int
siz[m],tot;
22ll ans;
23bool cmp(int x,int
y)24
27void
insert()
2836 ed[u]=1;37
}38void dfs1(int u,int
fa)39
45void dfs2(int
u)4654}
55void solve(int u,int
lst)
5665}66
intmain()
6774 dfs1(0,0
);75 dfs2(0
); 76 solve(0,1
);77 printf("
%lld\n
",ans);
78return0;
79 }
Scoi2016 背單詞(trie 貪心)
題意 重新解釋一下題意吧 題意晦澀難懂 給定n個單詞,你可以按照順序學習,當學習這一單詞時,這個單詞是第x個要學習的單詞,需要的代價分三類 1 若存在其他單詞是其字尾沒被學習,則代價為n2 2 若不存在其他單詞是其字尾,則代價是x 3 否則代價是x y y是最靠後的是其字尾的單詞學習的位置 題解 首...
SCOI2016 背單詞 題解
題意的話就看題面吧。我們一步一步的來分析 首先吃最少的泡椒,那麼顯然可以貪心,由於n n n times n n n貢獻的肯定比後面的方式都大,所以我們考慮將乙個串它的所有存在的字尾串全部先放在前面,這時就不會用第一種了,然後我們考慮,可以將這種關係用邊連起來,就成了一棵樹,我們可以舉個例子來看 5...
SCOI2016 幸運數字
線性基合併o log 2n 不能更小 但是倍增o qlog 3n 可過233333 甚至樹剖o qlog 4n 可過666666 還有乙個樹上路徑查詢利器 點分治!詢問離線 列舉重心,處理路徑過重心的詢問 邊dfs邊插入線性基,維護每個點到根路徑上的線性基 每個詢問,如果所屬不同的子樹,那麼過當前重...