POJ2452 Sticks Problem

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; //初始自身是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]];//递归计算

 

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的主要内容,如果未能解决你的问题,请参考以下文章

POJ#1011 Sticks

poj 1065 Wooden Sticks

poj 2452(RMQ+二分查找)

POJ 1011 Sticks DFS 剪枝

POJ 1011 Sticks

poj1011 Sticks