标签:max stdout mes -- open getch class div opera
A:搜索好难啊根本不会啊。
B:原题都能写挂没救了啊。考虑求出每个数作为最小值时能向左向右扩展到的最远位置,那么这段区间里的所有数就不可能作为唯一的最小值成为最优解了,否则假设可以的话这段区间里的数都能整除该数,也一定能整除之前找到的最小值,区间就可以扩展到这里。所以从左往右从右往左各扫一遍即可,注意各种细节。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 500010 int n,a[N],l[N],r[N],ans; struct data { int l,r; bool operator ==(const data&a) const { return l==a.l&&r==a.r; } bool operator <(const data&a) const { return l<a.l||l==a.l&&r<a.r; } }b[N]; int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); n=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<=n;i++) { r[i]=i; while (r[i]<n&&a[r[i]+1]%a[i]==0) r[i]++; while (i<r[i]) r[i+1]=r[i],i++; } for (int i=n;i>=1;i--) { l[i]=i; while (l[i]>1&&a[l[i]-1]%a[i]==0) l[i]--; while (i>l[i]) l[i-1]=l[i],i--; } for (int i=1;i<=n;i++) ans=max(ans,r[i]-l[i]); for (int i=1;i<=n;i++) b[i].l=l[i],b[i].r=r[i]; sort(b+1,b+n+1); int t=unique(b+1,b+n+1)-b-1;n=t; int cnt=0; for (int i=1;i<=n;i++) if (b[i].r-b[i].l==ans) cnt++; cout<<cnt<<‘ ‘<<ans<<endl; for (int i=1;i<=n;i++) if (b[i].r-b[i].l==ans) printf("%d ",b[i].l); return 0; }
C:可能连二分都不会了啊。设f[i][j]为前i行切j刀能得到的最大的最小值,转移时枚举上次切割位置二分答案算出来,复杂度n3log。然后就一直在想怎么利用各种单调性去log了,最后无果卡了一波常,最后卡进2s然后好像多拿了10分。正解直接二分答案明明非常显然啊怎么我不会啊。
result:180 rank8
标签:max stdout mes -- open getch class div opera
原文地址:https://www.cnblogs.com/Gloid/p/9744902.html