Codeforecs 359D Pair of Numbers 单调栈 OR ST表+二分

来源:互联网 发布:淘宝仓管的职责 编辑:程序博客网 时间:2024/05/22 02:13

点击打开链接

题意:n个数a[i],找到最长的一段区间[l,r],存在l<=j<=r 满足a[l],a[l+1]...a[r]都能被a[j]整除
如果最大长度有多个,输出所有开头. n<=3e5,a[i]<=1e6


法1:
枚举a[j] 处理出a[j]的左右边界即可.
因为a|b b|c 所以a|c 用单调栈处理边界 O(n)

法2:
[l,r]中的a[j]为 min(a[l],a[l+1]..a[r]) 要和gcd(a[l]..a[r]) 相等 
预处理出min和gcd的 ST表,二分长度,O(n)判断即可 O(nlogn).

#include <bits/stdc++.h>using namespace std;typedef long long ll;const double eps=1e-10;const int inf=0x3f3f3f3f;const int N=5e5+20;stack<int> s;int n,a[N],l[N],r[N],f[N];map<int,int> mp;vector<int> ans;int main(){while(cin>>n){mp.clear();ans.clear();for(int i=1;i<=n;i++){scanf("%d",&a[i]);while(!s.empty()&&a[i]%a[s.top()]){r[s.top()]=i-1;s.pop();}s.push(i);}while(!s.empty())r[s.top()]=n,s.pop();for(int i=n;i>=1;i--){while(!s.empty()&&a[i]%a[s.top()]){l[s.top()]=i+1;s.pop();}s.push(i);}while(!s.empty())l[s.top()]=1,s.pop();int mx=0;for(int i=1;i<=n;i++){f[i]=r[i]-l[i];mx=max(mx,f[i]);//cout<<l[i]<<' '<<r[i]<<endl;}for(int i=1;i<=n;i++)if(f[i]==mx&&!mp[l[i]])ans.push_back(l[i]),mp[l[i]]=1;cout<<ans.size()<<' '<<mx<<endl;for(int i=0;i<ans.size();i++)printf("%d ",ans[i]);printf("\n"); }return 0;}

法2代码转自点击打开链接

#include "cstdio"#include "iostream"#include "vector"#include "algorithm"#include "math.h"#include "cstring"using namespace std;#define lson l,mid,root<<1#define rson mid+1,r,root<<1|1#define maxn 3*100005#define maxp 20template <class T>inline bool read(T &ret){    char c;    int sgn;    if(c=getchar(),c==EOF) return 0; //EOF    while(c!='-'&&(c<'0'||c>'9')) c=getchar();    sgn=(c=='-')?-1:1;    ret=(c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    ret*=sgn;    return 1;}int gcd(int a,int b) {if(b!=0) return gcd(b,a%b);else return a;}int RMQ[maxn][maxp],GCD[maxn][maxp],val[maxn],n,cnt,range;vector<int> ans;void ST(){    for(int i=1;i<=n;i++) RMQ[i][0]=GCD[i][0]=val[i];    for(int j=1;(1<<j)<=n;j++)        for(int i=1;i+(1<<j)-1<=n;i++)    {        RMQ[i][j]=min(RMQ[i][j-1],RMQ[i+(1<<(j-1))][j-1]);        GCD[i][j]=gcd(GCD[i][j-1],GCD[i+(1<<(j-1))][j-1]);    }}bool Query(int L,int R){    int k=0;    while((1<<(k+1))<=R-L+1) k++;    int a=min(RMQ[L][k],RMQ[R-(1<<k)+1][k]);    int b=gcd(GCD[L][k],GCD[R-(1<<k)+1][k]);    if(a==b) return true;    else return false;}bool judge(int v) //枚举r-l{    int cc=0;    vector<int> tt;    for(int i=1; v+i<=n; i++)    {        if(Query(i,i+v)) //L=i,R=i+v;        {            cc++;            tt.push_back(i);        }    }    if(cc>0)    {        ans=tt;        cnt=cc;        range=v;        return true;    }    return false;}int main(){    memset(RMQ,1,sizeof(RMQ));    memset(GCD,1,sizeof(GCD));    read(n);    for(int i=1; i<=n; i++)        read(val[i]);    ST();    int l=0,r=n-1,mid;    while(l<=r)  //二分    {        mid=(l+r)>>1;        if(judge(mid)) l=mid+1;        else r=mid-1;    }    printf("%d %d\n",cnt,range);    for(int i=0;i<ans.size();i++) {if(i>0) printf(" ");printf("%d",ans[i]);};    printf("\n");}



原创粉丝点击