NOI2015 品酒大會

2022-05-10 22:14:10 字數 3924 閱讀 8244

一年一度的「幻影閣夏日品酒大會」隆重開幕了。大會包含品嚐和趣味挑戰 兩個環節,分別向優勝者頒發「首席品酒家」和「首席獵手」兩個獎項,吸引了眾多品酒師參加。

在大會的晚餐上,調酒師 rainbow 調製了 n 杯雞尾酒。這 n 杯雞尾酒排成一行,其中第 n 杯酒 (1 ≤ i ≤ n) 被貼上了乙個標籤si,每個標籤都是 26 個小寫 英文本母之一。設 str(l, r)表示第 l 杯酒到第 r 杯酒的 r − l + 1 個標籤順次連線構成的字串。若 str(p, po) = str(q, qo),其中 1 ≤ p ≤ po ≤ n, 1 ≤ q ≤ qo ≤ n, p ≠ q, po − p + 1 = qo − q + 1 = r ,則稱第 p 杯酒與第 q 杯酒是「 r 相似」 的。當然兩杯「 r 相似」(r > 1)的酒同時也是「 1 相似」、「 2 相似」、……、「 (r − 1) 相似」的。特別地,對於任意的 1 ≤ p , q ≤ n , p ≠ q ,第 p 杯酒和第 q 杯酒都 是「 0 相似」的。

在品嚐環節上,品酒師 freda 輕鬆地評定了每一杯酒的美味度,憑藉其專業的水準和經驗成功奪取了「首席品酒家」的稱號,其中第 i 杯酒 (1 ≤ i ≤ n) 的 美味度為 ai 。現在 rainbow 公布了挑戰環節的問題:本次大會調製的雞尾酒有乙個特點,如果把第 p 杯酒與第 q 杯酒調兌在一起,將得到一杯美味度為 ap*aq 的 酒。現在請各位品酒師分別對於 r = 0,1,2, ⋯ , n − 1 ,統計出有多少種方法可以 選出 2 杯「 r 相似」的酒,並回答選擇 2 杯「 r 相似」的酒調兌可以得到的美味度的最大值。

輸入格式:

第 1 行包含 1 個正整數 n ,表示雞尾酒的杯數。

第 2 行包含乙個長度為 n 的字串 s,其中第 i 個字元表示第 i 杯酒的標籤。

第 3 行包含 n 個整數,相鄰整數之間用單個空格隔開,其中第 i 個整數表示第 i 杯酒的美味度 ai 。

輸出格式:

包括 n 行。第 i 行輸出 2 個整數,中間用單個空格隔開。第 1 個整 數表示選出兩杯「 (i − 1)

相似」的酒的方案數,第 2 個整數表示選出兩杯 「 (i − 1) 相似」的酒調兌可以得到的最大美味度。若不存在兩杯「 (i − 1) 相似」

的酒,這兩個數均為 0 。

輸入樣例#1:複製

10

ponoiiipoi

2 1 4 7 4 8 3 6 4 7

輸出樣例#1:複製

45 56

10 56

3 32

0 00 0

0 00 0

0 00 0

0 0

輸入樣例#2:複製

12

abaabaabaaba

1 -2 3 -4 5 -6 7 -8 9 -10 11 -12

輸出樣例#2:複製

66 120

34 120

15 55

12 40

9 27

7 16

5 73 -4

2 -4

1 -4

0 00 0

【樣例說明 1】

用二元組 (p, q) 表示第 p 杯酒與第 q 杯酒。

0 相似:所有 45 對二元組都是 0 相似的,美味度最大的是 8 × 7 = 56 。

1 相似: (1,8) (2,4) (2,9) (4,9) (5,6) (5,7) (5,10) (6,7) (6,10) (7,10) ,最大的 8 × 7 = 56 。

2 相似: (1,8) (4,9) (5,6) ,最大的 4 × 8 = 32 。

沒有 3,4,5, ⋯ ,9 相似的兩杯酒,故均輸出 0 。

問題轉化為分別求lcp>=r的字尾的組數

lcp為l的一組 對後面的l-1 l-2 l-3....也可以貢獻

求出每個height

實際上對於每個(i,j),他的lcp都應當統計

可以單獨考慮每個height的貢獻

l[i]表示最靠左的不大於它的位置

r[i]表示最靠右的大於它的位置(避免重複計算)

那麼height[i]的貢獻就是(i-l[i]+1)*(r[i]-i+1)

對於第二問,對左右取最大值相乘,再取最小值相乘,用st表

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;

7 typedef long

long

lol;

8 lol ans[300001],sum[300001];9

intn,m;

10 lol min[300001][21],max[300001][21],w[300001

];11

int c[300001],x[300001],y[300001

];12

int sa[300001],rank[300001],s[300001],h[300001],log[300001

];13 lol st[300001],l[300001],r[300001

];14

char ch[300001

];15

void

radix_sort()

16 26

void

build_sa()

27 47

for (i=1;i<=n;i++)

48 rank[sa[i]]=i;

49int l=0;50

for (i=1;i<=n;i++)

5157

}58 lol rmq_max(int x,int

y)59

63 lol rmq_min(int x,int

y)64

68int

main()

6977

for (i=1;i<=n;i++)

7881

build_sa();

82for (i=1;i<=n;i++)

83 min[i][0]=max[i][0]=w[sa[i]];

84for (j=1;(1

8591}92

for (i=1;i<=n;i++)

9399 log[1]=0

;100

for (i=2;i<=n;i++)

101 log[i]=log[i/2]+1

;102 top=0

;103

for (i=n;i>=1;i--)

104110

for (i=0;i<=n;i++)

111 ans[i]=-2e18;

112for (i=1;i<=n;i++)

113118

for (i=n-2;i>=0;i--)

119123 sum[0]=(n-1)*n/2

;124

for (i=0;i<=n-1;i++)

125 printf("

%lld %lld\n

",sum[i],ans[i]==-2e18?0

:ans[i]);

126 }

Noi 2015 品酒大會

題目等價於求任意兩對字尾的lcp的值小於等於1,2 n的個數,以及權值乘積的最大值。求出字尾陣列的height值,然後預處理出每個height值能夠成為最小的區間。考慮每個height的值對答案的貢獻 如果height i 能夠成為最小的區間為 l,r 那麼個數便是 l i 1 r i 1 而乘積最...

NOI2015 品酒大會

字尾自動機 首先考慮第一問 我們先將字尾自動機建出來,考慮每個節點,它出現的次數肯定是endpos的size 我們記為num 那麼選取這個節點的串的方案數即為c num,2 num num 1 2,所能貢獻的長度區間為這個節點對應的所有串的長度即 len fa x 1 len x 1 這裡可以差分一...

NOI2015 品酒大會

一年一度的 幻影閣夏日品酒大會 隆重開幕了。大會包含品嚐和趣味挑戰 兩個環節,分別向優勝者頒發 首席品酒家 和 首席獵手 兩個獎項,吸引了眾多品酒師參加。在大會的晚餐上,調酒師 rainbow 調製了 n 杯雞尾酒。這 n 杯雞尾酒排成一行,其中第 n 杯酒 1 i n 被貼上了乙個標籤si,每個標...