P7244-章节划分【RMQ,贪心,递归】
生活随笔
收集整理的這篇文章主要介紹了
P7244-章节划分【RMQ,贪心,递归】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P7244?contestId=38911
題目大意
nnn個數字,分成連續非空的kkk段要求每一段的最大值的gcdgcdgcd最大。
解題思路
首先答案一定是最大值的約數,這些數不多我們可以枚舉這些數xxx。然后我們稱xxx的倍數的位置為關鍵點。
現在我們要求在選取的全都是關鍵點的情況下最多能夠選取的關鍵點數量
我們先找出最大的數(第一次肯定是最大的那個數)然后如果這個數是xxx的倍數就遞歸左右兩邊把數量加起來。如果不是我們就比較這個點和區間的左右兩邊(一定是空的或者是關鍵點),如果一邊比這個數要大就可以遞歸另一邊(那一邊的那個數區間延伸過來),如果兩邊都比這個數要大就取兩邊的最大值即可。
RMQRMQRMQ維護區間最大的位置即可
時間復雜度O(nlog?n+namax)O(n\log n+n\sqrt {a_{max}})O(nlogn+namax??)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10,T=20; int n,m,a[N],f[N][T],lg[N],ans; int rmq(int l,int r){int z=lg[r-l+1];return (a[f[l][z]]>a[f[r+1-(1<<z)][z]])?f[l][z]:f[r+1-(1<<z)][z]; } int calc(int l,int r,int pl,int pr,int x){if(l>r)return 0;int k=rmq(l,r),tmp=0;if(a[k]%x==0)return calc(l,k-1,pl,a[k],x)+calc(k+1,r,a[k],pr,x)+1;if(a[k]<pr)tmp=max(tmp,calc(l,k-1,pl,pr,x));if(a[k]<pl)tmp=max(tmp,calc(k+1,r,pl,pr,x));if(a[k]>pl&&a[k]>pr)return -1e9;return tmp; } void solve(int x){int k=rmq(1,n);if(calc(1,k-1,0,a[k],x)+calc(k+1,n,a[k],0,x)+1>=m)ans=max(ans,x);return; } int main() {scanf("%d%d",&n,&m);int w=0;lg[0]=-1;for(int i=1;i<=n;i++){scanf("%d",&a[i]);w=max(w,a[i]);f[i][0]=i;lg[i]=lg[i/2]+1;}for(int j=1;(1<<j)<=n;j++)for(int i=1;i+(1<<j)-1<=n;i++){if(a[f[i][j-1]]>a[f[i+(1<<j-1)][j-1]])f[i][j]=f[i][j-1];else f[i][j]=f[i+(1<<j-1)][j-1];}for(int i=1;i*i<=w;i++){if(w%i==0){solve(i);if(i*i!=w)solve(w/i);}}printf("%d\n",ans);return 0; }總結
以上是生活随笔為你收集整理的P7244-章节划分【RMQ,贪心,递归】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中等配置的电脑大概多少钱(中等配置的电脑
- 下一篇: AT3955-[AGC023D]Go H