題解 TJOI HEOI2016 字串

2022-05-02 01:57:07 字數 1587 閱讀 7533

loj

二分答案 \(mid\).

考慮字尾陣列求出的陣列,那麼只要看 \(sa\) 陣列裡的

包含 \(c\) 開頭的字尾的

一段滿足最長公共字首 \(\geq mid\) 的區間裡,有沒有開頭在 \([a,b-mid+1]\) 中的字尾即可.

(可能上面那段話太模糊,請繼續看下去)

具體來說,先求出乙個 \(l\),滿足 \(sa\) 陣列中 \([l,c]\) 這段區間的最長公共字首都 \(\geq mid\).

再求 \(r\),滿足 \(sa\) 陣列中 \(c,r\) 這段區間的最長公共字首 \(\geq mid\).

那麼如果有開頭

在 \(sa\) 陣列中的 \([l,r]\) 範圍內,

且在原串中 \([a,b-mid+1]\) 內

的字尾,

則答案 \(\geq mid\).

那麼 \(l,r\) 可以在求出 \(height\) 陣列的 \(\texttt\) 表後,二分答案求.

而判斷 \([l,r]\) 中是否有開頭在 \([a,b-mid+1]\) 中的點的字尾,

可以以 \(rk\) 作為下標,建主席樹,

每次查詢 \([a,b-mid+1]\) 中的下標在 \([l,r]\) 中的個數,如果 \(>0\) 則說明存在.

這題需要對字尾陣列,主席樹的靈活運用,並需要一些做題技巧(二分答案).

#include #include #include #define ll long long

using namespace std;

inline int read()

while(c<='9'&&c>='0')

return f*sum;

}const int n=200005;

int n,q;

char ss[n];

namespace sa

int k=0;

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

for(int i=1;i<=n;i++) s[i][0]=ht[i];

for(int j=1;j<18;j++)

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

if(i+(1<<(j-1))<=n) s[i][j]=min(s[i][j-1],s[i+(1<<(j-1))][j-1]);

lg[0]=-1;

for(int i=1;i<=n;i++) lg[i]=lg[i>>1]+1;

} inline int lcp(int l,int r)

inline int query(int p1,int p2,int l,int r,int ql,int qr)

};using namespace tr;

signed main()

l=rk[c];r=n;

while(l<=r)

if(query(rt[a-1],rt[(mid? b-mid+1:b)],1,n,pl,pr)) ans=mid,l=mid+1;

else r=mid-1;

} printf("%d\n",ans);

} return 0;

}

題解 SDOI2016 征途

link 題目大意 給定序列,將它劃分為 m 段使得方差最小,輸出 s 2 m 2 乙個整數 text 這題我通過題解中的大佬部落格學到了一般化方差柿子的寫法。下面來推柿子 s 2 frac n x i overline 2 frac sum n x i 2 n frac n x i 2 2 sum...

SDOI2016 遊戲題解

這道題太噁心了,調了我整整一晚上,結果發現是乙個bi 錯誤,多多捂臉 這道題比之前的題多了乙個初始化和區間查詢的操作,主要是區間查詢噁心 因為要區間查詢,所以必須維護區間最低點,修改和查詢操作被改得面目全非。我們要維護的話,必須從現值,子值,新值,具體的不好多說 看 吧 include define...

2016程設期末偽題解

期末發揮實在是太差了 比2015年少了好多送分題,整體難度顯得很大,但是考完之後靜下來做又覺得並不是很難orz 1.籃球聯賽 暴力列舉 我用的 dfs 來列舉 2.奪寶探險 暴力 dfs 3.尋找邊緣 從邊緣暴力 dfs 4.猴子摘桃 可以直接用兩個指標指向區間端點做到 o n 5.分形盒 直接遞迴...