Beauty Of Unimodal Sequence(HDU-6592)
Problem Description
You are given an array of?n?integers?a1,a2,...,an. We define that a sequence?p1,p2,...,pk(k∈[1,n])?is beautiful if and only if these conditions are met:
- ?1≤p1<p2<?<pk≤n.
- ?There exists?t(t∈[1,k])?satisfying?ap1<ap2<?<apt?and?apt>apt+1>?>apk.
You need to find all the longest beautiful sequences, and output the lexicographically smallest one and the lexicographically largest one in them.
Check the examples below for better understanding.
Input
There are multiple test cases.
Each case starts with a line containing a positive integer?n(n≤3×105).
The second line contains?n?integers?a1,a2,...,an(1≤ai≤109).
It is guaranteed that the sum of?Ns in all test cases is no larger than?106.
Output
For each test case, output two lines, the first of which depicts the lexicographically smallest one in longest beautiful sequences and the second of which depicts the lexicographically largest one in longest beautiful sequences.
Sample Input
7
1 4 2 5 7 4 6
3
1 2 3
3
3 2 1
Sample Output
1 2 4 5 6
1 3 4 5 7
1 2 3
1 2 3
1 2 3
1 2 3
題意:t 組數(shù)據(jù),每組給出一個(gè)長(zhǎng)度為 n 的序列 a,求序列 a 的最長(zhǎng)的字典序最小的單峰子序列、最大的單峰子序列
思路:
由于要求一個(gè)單峰子序列,那么可以正反各求一遍最長(zhǎng)上升子序列 LIS,然后進(jìn)行模擬來(lái)尋找單峰子序列
求字典序最小時(shí),首先找到第一個(gè)峰,然后利用單調(diào)棧從后向前找遞減的序列中下標(biāo)較小的,再向后找嚴(yán)格遞減的
求字典序最大時(shí),首先找到最大的一個(gè)峰,然后從后向前依次找嚴(yán)格遞減的,再向后找 LIS 中下標(biāo)大的
Source Program
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<unordered_map> #include<bitset> #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LL long long #define Pair pair<LL,LL> LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; } LL quickModPow(LL a,LL b,LL mod){ LL res=1; a=a%mod; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1;} return res; } LL getInv(LL a,LL mod){ return quickModPow(a,mod-2,mod); } LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); } LL LCM(LL x,LL y){ return x/GCD(x,y)*y; } const double EPS = 1E-10; const int MOD = 998244353; const int N = 500000+5; const int dx[] = {-1,1,0,0,1,-1,1,1}; const int dy[] = {0,0,-1,1,-1,1,-1,1}; using namespace std;int a[N],pos1[N],pos2[N]; int dp[N]; int pos[N]; void getLIS(int n){//正著求一遍L(zhǎng)ISmemset(dp,INF,sizeof(dp));dp[0]=0;for(int i=1; i<=n; i++) { //正著求一遍L(zhǎng)ISpos1[i] = lower_bound(dp+1, dp+n+1, a[i])-dp;dp[pos1[i]]=a[i];}//反著求一遍L(zhǎng)ISmemset(dp,INF,sizeof(dp));dp[0]=0;for(int i=n;i>0;i--){pos2[i]=lower_bound(dp+1, dp+n+1, a[i])-dp;dp[pos2[i]]=a[i];} } vector<int> getSmallLEX(int n){int index=1;//記錄下標(biāo)int maxx=pos1[1]+pos2[1];for(int i=2; i<=n; i++) { //尋找第一個(gè)峰if(pos1[i]+pos2[i]>maxx) {maxx=pos1[i]+pos2[i];index=i;}}pos[pos1[index]]=a[index];stack<int> S;for(int i=index-1; i>0; i--) { //利用單調(diào)棧尋找滿足LIS的下標(biāo)if(a[i]>=pos[pos1[i]+1])continue;while(!S.empty()&&pos1[S.top()]<=pos1[i])S.pop();S.push(i);pos[pos1[i]]=a[i];}vector<int> res;while(!S.empty()) { //保存結(jié)果int temp=S.top();S.pop();res.push_back(temp);}res.push_back(index);for(int i=index+1; i<=n; i++) { //從第一個(gè)峰向后找遞減的int len=res.size();if(pos2[i]==pos2[res[len-1]]-1 && a[i]<a[res[len-1]])res.push_back(i);}return res; } vector<int> getLargeLEX(int n){int index=1;int maxx=pos1[1]+pos2[1];for(int i=2; i<=n; i++) { //找最后一個(gè)峰if(pos1[i]+pos2[i]>=maxx){maxx=pos1[i]+pos2[i];index=i;}}memset(pos, INF, sizeof(pos));stack<int> S;S.push(index);for(int i=index-1; i>0 ;i--) {//從前向后找遞減的if(pos1[i]==pos1[S.top()]-1 && a[i]<a[S.top()])S.push(i);}vector<int> res;while(!S.empty()){int temp=S.top();S.pop();res.push_back(temp);}for(int i=index+1; i<=n ;i++){if(a[i]>=pos[pos2[i]+1])continue;while(res.size()>=0 && pos2[i]>=pos2[res[res.size()-1]])res.pop_back();res.push_back(i);pos[pos2[i]]=a[i];}return res; } int main(){int n;while (scanf("%d",&n)!=EOF) {for(int i=1;i<=n;i++)scanf("%d",&a[i]);getLIS(n);vector<int> small=getSmallLEX(n);vector<int> large=getLargeLEX(n);int len=small.size();for(int i=0; i<len-1; i++)printf("%d ",small[i]);printf("%d\n",small[len-1]);for(int i=0; i<len-1; i++)printf("%d ",large[i]);printf("%d\n",large[len-1]);}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的Beauty Of Unimodal Sequence(HDU-6592)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Oulipo(POJ-3461)
- 下一篇: 字符串处理 —— 回文串相关