【ST表】栈(jzoj 2295)
生活随笔
收集整理的這篇文章主要介紹了
【ST表】栈(jzoj 2295)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
棧
jzoj 2295
題目大意:
有一個A數組,一個B數組和一個棧,現在把A數組的數存入棧(操作1),然后再從棧中取出來放在B數組,但取出可以從棧頂(操作2),也可以從棧底(操作3),現在問怎樣操作可以使B數組的字典序最小
輸入樣例
5 1 4 3 5 2輸出樣例
1 2 4 3 5數據范圍
對于10%的數據,n?5n \leqslant 5n?5;
對于30%的數據,n?1000n \leqslant 1000n?1000;
對于100%的數據,n?100000n \leqslant 100000n?100000,保證給出的AiA_iAi?是1~n1\sim n1~n 的一個排列;
樣例解釋
依次使用操作 1、2、1、1、1、1、2、3、3、2 可以得到樣例輸出 1 2 4 3 5 。
解題思路:
因為要求的是字典序最小的,所以我們每一個數字都要盡量小,我們可以拿的有棧的兩端和A數列剩下的所有數(剩下的數求最大可以用ST表),我們選最小的,如果選的是A數列剩下的數中最小的,那我們讓這個數前面的數全部入棧
代碼:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int MAXX=100500; int n,w,l,r,bg,s1,s2,minn,a[MAXX],p[MAXX],f[MAXX][20],s[MAXX][20]; void js(int l,int r)//查詢ST表 {if (l>r){minn=MAXX;return;}int k=log(r-l+1)/log(2);if (f[l][k]<f[r-(1<<k)+1][k]){minn=f[l][k];//最小值w=s[l][k];//位置}else{minn=f[r-(1<<k)+1][k];w=s[r-(1<<k)+1][k];} } int main() {scanf("%d",&n);for (int i=1;i<=n;++i){scanf("%d",&a[i]);f[i][0]=a[i];s[i][0]=i;}int t=log(n)/log(2)+1;for (int j=1;j<t;++j)//建ST表for (int i=1;i<=n-(1<<j)+1;++i)if (f[i][j-1]<f[i+(1<<(j-1))][j-1]){f[i][j]=f[i][j-1];s[i][j]=s[i][j-1];}else{f[i][j]=f[i+(1<<(j-1))][j-1];s[i][j]=s[i+(1<<(j-1))][j-1];}l=1;r=0;bg=1;a[0]=MAXX;for (int i=1;i<=n;++i){while(p[l]&&l<=r) l++;//去掉選過的while(p[r]&&l<=r) r--;if (l<=r) s1=a[l],s2=a[r];//判斷棧是否為空else s1=s2=MAXX;js(bg,n);if (minn<s1&&minn<s2)//l,r表示棧的范圍,bg表示A序列的開始位置{printf("%d ",minn);p[w]=1;//記錄bg=w+1;//A序列的開始位置在這個點后面+1r=w-1;//前面的全部入棧}else if(s1<s2)//從棧底取出{printf("%d ",s1);p[l]=1;l++;}else{printf("%d ",s2);//從棧頂取出p[r]=1;r--;}} }總結
以上是生活随笔為你收集整理的【ST表】栈(jzoj 2295)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 城市文化笔记整理(二)
- 下一篇: 【bfs】神殿(jzoj 2296)