給出乙個序列$ 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個石子,兩人輪流對石子塗色 先手塗紅,後手塗藍 且需要保證當前回合塗的石子顏色不能和它相鄰的兩個同色,誰塗不下去誰輸。一...