首页 > 代码库 > POJ2452 Sticks Problem

POJ2452 Sticks Problem

题解:

这题可以rmq+二分做,也可以单调栈+线性扫

单调栈+线性扫:

对a[i],d[i]表示以a[i]为起点,大于a[i]的最长长度

例如

a     4 3 5 6

dis  1 3 2 1

然后对于每个dis,求出枚举最大值的位置。更新即可..

关键是求dis.这里用到了单调栈的思想

for(int i=1;i<=n;i++) dis[i]=1; //初始自身是1a[n+1]=0;for(int i=n;i>=1;i--) while(a[i]<a[i+dis[i]]) dis[i]+=dis[i+dis[i]];//递归计算

 

rmq+二分做:

对于a[i],求出a[i--j]均大于a[i]的最大j,然后在a[i--j]中找寻最大值a[k]//然后更新即可

第二步:直接rmq_max(i,j)

第一步:二分(i+1,n)+rmq_min()

int bs(int x,int l){    int Goal=x,L=l,R=n,M;    while(L<=R){        M=(L+R)>>1;        if(a[x]<rmq_min(L,M)){            Goal=M;            L=M+1;        }        else R=M-1;    }    return Goal;}

rmq+二分做法注意要hash。如果直接用map会TLE。

也可以不用hash,直接将rmq映射到数组a上,这样就要重新写min,max

代码:

单调栈+线性扫:

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<map>#include<set>#include<vector>using namespace std;using namespace std;#define pb push_back#define mp make_pair#define se second#define fs first#define ll long long#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define ls o<<1#define rs o<<1|1#define SZ(x) ((int)(x).size())#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)typedef pair<int,int> P;const double eps=1e-9;const int maxn=100100;const int N=1e9;const int mod=1e9+7;ll read(){    ll x=0,f=1;char ch=getchar();    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}    return x*f;}//-----------------------------------------------------------------------------int a[maxn],dis[maxn];int n,Max,flag,ans;int main(){    while(~scanf("%d",&n))    {        ans=0;        for(int i=1;i<=n;i++) scanf("%d",&a[i]);        for(int i=1;i<=n;i++) dis[i]=1;        a[n+1]=0;        for(int i=n;i>=1;i--)  while(a[i]<a[i+dis[i]]) dis[i]+=dis[i+dis[i]];        for(int i=1;i<=n;i+=flag+1)        {            Max=-1;            flag=-1;            for(int j=0;j<dis[i];j++)            {                if(a[i+j]>Max)                {                    Max=a[i+j];                    flag=j;                }            }            ans=max(ans,flag);        }        if(ans) printf("%d\n",ans);        else printf("-1\n");    }    return 0;}

rmq+二分

1.hash

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<map>#include<set>#include<vector>using namespace std;using namespace std;#define pb push_back#define mp make_pair#define se second#define fs first#define ll long long#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define ls o<<1#define rs o<<1|1#define SZ(x) ((int)(x).size())#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)typedef pair<int,int> P;const double eps=1e-9;const int maxn=100100;const int N=1e9;const int mod=1e9+7;ll read(){    ll x=0,f=1;char ch=getchar();    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}    return x*f;}//-----------------------------------------------------------------------------int n;int a[maxn],mi[maxn][20],mx[maxn][20];int hash[maxn];void rmq_init(){    for(int i=1;i<=n;i++) mi[i][0]=mx[i][0]=a[i];    int k=(int)(log(n*1.0)/log(2.0));    for(int i=1;i<=k;i++)    for(int j=1;j<=n;j++){        mi[j][i]=mi[j][i-1];        if(j+(1<<(i-1))<=n) mi[j][i]=min(mi[j][i],mi[j+(1<<(i-1))][i-1]);        mx[j][i]=mx[j][i-1];        if(j+(1<<(i-1))<=n) mx[j][i]=max(mx[j][i],mx[j+(1<<(i-1))][i-1]);    }}int rmq_min(int l,int r){    int k=(int)(log((r-l+1.0)*1.0)/log(2.0));    return min(mi[l][k],mi[r-(1<<k)+1][k]);}int rmq_max(int l,int r){    int k=(int)(log((r-l+1.0)*1.0)/log(2.0));    return max(mx[l][k],mx[r-(1<<k)+1][k]);}int bs(int x,int l){    int Goal=x,L=l,R=n,M;    while(L<=R){        M=(L+R)>>1;        if(a[x]<rmq_min(L,M)){            Goal=M;            L=M+1;        }        else R=M-1;    }    return Goal;}int main(){    while(~scanf("%d",&n)){        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);            hash[a[i]]=i;        }        rmq_init();        int Max=0;        for(int i=1;i+Max<n;i++){            int pos=bs(i,i+1);            pos=hash[rmq_max(i,pos)];            Max=max(Max,pos-i);        }        if(Max==0) printf("-1\n");        else printf("%d\n",Max);    }    return 0;}

2.映射

#include<iostream>  #include<cstdio>  #include<cstring>  #include<cmath>  using namespace std;    const int maxn = 50005;  int n,stick[maxn],dp_max[maxn][20],dp_min[maxn][20];    int _max(int l,int r)  {      if(stick[l] > stick[r]) return l;      return r;  }    int _min(int l,int r)  {      if(stick[l] < stick[r]) return l;      return r;  }    void initRMQ()  {      for(int i = 1; i <= n; i++)          dp_max[i][0] = dp_min[i][0] = i;      for(int j = 1; (1 << j) <= n; j++)          for(int i = 1; i + (1 << j) - 1 <= n; i++)          {              dp_max[i][j] = _max(dp_max[i][j-1],dp_max[i+(1<<j-1)][j-1]);              dp_min[i][j] = _min(dp_min[i][j-1],dp_min[i+(1<<j-1)][j-1]);          }  }    int MaxValue(int l,int r)  {      int k = (int)(log(double(r) - l + 1) / log(2.0));        return _max(dp_max[l][k],dp_max[r-(1<<k)+1][k]);  }    int MinValue(int l,int r)  {      int k = (int)(log(double(r) - l + 1) / log(2.0));        return _min(dp_min[l][k],dp_min[r-(1<<k)+1][k]);  }    int binsearch(int x,int l,int r)  {      int goal=x;    while(l <= r)      {          int mid = (l + r) >> 1;          if(stick[x] < stick[MinValue(l,mid)]) {            goal=mid;            l=mid+1;        }          else r = mid-1;      }      return goal;  }    int main()  {      while(scanf("%d",&n)!=EOF)      {          for(int i = 1; i <= n; i++)              scanf("%d",&stick[i]);          initRMQ();          int ans = 0;          for(int i = 1; i + ans < n; i++)          {              int r = binsearch(i,i+1,n);              int k = MaxValue(i,r);              if(stick[k] > stick[i])                  ans = max(ans,k - i);          }          if(ans == 0) printf("-1\n");          else printf("%d\n",ans);      }      return 0;  }  

 

POJ2452 Sticks Problem