牛客網NOIP賽前集訓營 提高組(第四場)B區間

2022-05-02 08:03:12 字數 1574 閱讀 6465

給出乙個序列$ a_1\ \ \dots\ \ a_n$。

定義乙個區間 \([l,r]\) 是好的,當且僅當這個區間中存在乙個 \(i\),使得 \(a_i\) 恰好等於 \(a_l, a_ \ \ \dots \ \ a_, a_r\) 的最大公因數。

求最長的好的區間的長度。

第一行 n,表示序列的長度;

第二行 n 個數 a1,a2,...,an。

輸出一行乙個數,表示最長的好的區間的長度。
亂搞就行,考試的時候睡了一覺就想出來了

用\(f[i]\) 表示前面第乙個能被\(a[i]\)整除的位置

用\(g[i]\) 表示後面第乙個能被\(a[i]\)整除的位置

則可以遞推

f[1]=1;

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

g[n]=n;

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

最後在\(f\)和\(g\)裡面連續的一段取最長的就行了

但是如果有這種資料:

5

10 6 6 6 9

我們寫出\(f\)和\(g\):

f: 1 2 2 2 5

g: 1 4 4 4 5

發現有重複數字時位置會不一樣

所以再用兩個陣列\(l[i]\)和\(r[i]\)亂搞一下

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

r[f[i]]=max(r[f[i]],i),

l[g[i]]=min(l[g[i]],i);

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

r[i]=max(r[i],r[f[i]]),

l[i]=min(l[i],l[g[i]]);

for(int i=1;i<=n;++i)ans=max(ans,r[i]-l[i]+1);

注意卡讀入,用fread或者ios和tie優化都行

然後就沒有然後了

可能我的思路比較別緻

#includeusing namespace std;

const int maxn = 4e6+5;

#define int long long

char getc()

int mian()

int a[maxn],n,f[maxn],g[maxn],ans,l[maxn],r[maxn];

signed main()

g[n]=n;

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

if(a[i]%a[g[i+1]]==0)g[i]=g[i+1];

else g[i]=i;

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

r[f[i]]=max(r[f[i]],i),

l[g[i]]=min(l[g[i]],i);

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

for(int i=1;i<=n;++i)ans=max(ans,r[i]-l[i]+1);

cout《讓我們一起膜拜大佬@olinr

2020牛客NOIP賽前集訓營 提高組(第四場)

有 f n 2 f 2 f 1 f 2 f 2 f 2 令 g n f n 2 很自然的有 g n 2g 2g g 將遞推式寫成矩陣的形式 a 令 vec n 為 g n,g g t 可以逆推出 vec 0 把 vec 表示成 a n vec 將題目中的 f s sum limits g sum l...

牛客CSP S提高組賽前集訓營2

然後隨便用乙個資料結構維護一下就行了,我寫的線段樹。我們先找出每個環,然後我們先刪連線環的邊,每刪一條就可以多產生乙個聯通塊,在考慮刪環邊,發現從最大的環刪起一定最優 因為你刪的第一條邊得不到任何新的聯通塊 就很容易想到tar jantarjan tarjan 發現你只能寫出80 8080 分,因為...

牛客CSP S提高組賽前集訓營1

比賽鏈結 官方題解 before t1觀察 結論題,t2樹形dp,可以換根或up down,t3正解妙,轉化為圖上問題。題目質量不錯,但資料太水了 一共n個石子堆,每個石子堆有ai個石子,兩人輪流對石子塗色 先手塗紅,後手塗藍 且需要保證當前回合塗的石子顏色不能和它相鄰的兩個同色,誰塗不下去誰輸。一...