5 条题解
-
0
首先我们发现我们要对于每一个数找到其左边右边第一个不能整除的数
找每个数左边右边第一个比其大和比其小的时候都使用单调栈,所以这道题考虑使用单调栈
这个单调栈里面的数需满足:相邻两个数之间呈倍数关系。入栈的时候若不满足,就弹出栈顶,直到满足。
因此,一个数被谁弹出栈,它右侧第一个它不能整除的数就是谁
正着反着跑两遍即可。
目前最优解
#include<algorithm> #include<iostream> #include<cstdio> #include<stack> #define N 300005 using namespace std; bool Test_MLE_start; int _=1,n,cnt=0,ans=0,top=0,a[N],L[N],R[N],p[N],stk[N]; //stack<int> stk; inline int reads(){ // char buf[1<<20],*p1,*p2; // #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++) int c=getchar(),x=0,f=1; while(!isdigit(c)) c=getchar_unlocked(); while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar_unlocked();} return x*f; }inline void files(){ freopen("A.in","r",stdin); // freopen("std.ans","w",stdout); }inline void clr(){ // Don't forget! }int gcd(int a,int b){return b?gcd(b,a%b):a;} bool Test_MLE_end; signed main(){ // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // _=reads(); while(_--){ clr();n=reads(); for(int i(1);i<=n;i++) a[i]=reads(); for(int i(1);i<=n;i++){ while(top&&(a[stk[top]]>a[i]||a[i]%a[stk[top]]!=0)) R[stk[top--]]=i; stk[++top]=i; }while(top) R[stk[top--]]=n+1; for(int i(n);i>=1;i--){ while(top&&(a[stk[top]]>a[i]||a[i]%a[stk[top]]!=0)) L[stk[top--]]=i; stk[++top]=i; }while(top) L[stk[top--]]=0; for(int i(1);i<=n;i++){ if(R[i]-L[i]-1>ans){ ans=R[i]-L[i]-1; p[cnt=1]=L[i]+1; }else if(R[i]-L[i]-1==ans&&p[cnt]!=L[i]+1) p[++cnt]=L[i]+1; }printf("%d %d\n",cnt,ans); for(int i=1;i<=cnt;i++) printf("%d ",p[i]); }exit(0); } /* 14 61 30 28 31 23 28 54 56 24 12 28 54 47 67 */
信息
- ID
- 571
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 121
- 已通过
- 20
- 上传者