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