<address id="xvfrz"></address>

              HDU6592 Beauty Of Unimodal Sequence

              Beauty Of Unimodal Sequence

              给一个序列,在满足单调递增或者单调递减或者先增后减的最长子序列集合里找到下标字典序最大以及最小的两个子序列,输出这两个子序列里元素的下标。

              n≤3×105

              moomhxy的题解

              先正着求一遍LIS,再反着求一遍LIS,求出每个点作为上升子序列结尾的最大长度和每个点作为下降子序列开头的最大长度。

              我们可以枚举这个单峰序列的峰顶是什么,这样最长长度就找到了。

              然后考虑怎么构造解。

              求字典序最小的话,首先找到第一个顶峰,然后往前找递减的序列中下标较小的,往后就依次找,这样能保证字典序最小。

              如何找这个下标较小的呢?显然我们希望每种结尾长度的点都越靠前越好。所以用单调栈维护即可。

              最大的话找到最后一个顶峰,往前是依次找,往后是找LIS中下标大的。维护方法类似。

              时间复杂度 O(n log n),瓶颈在于求LIS。

              CO int N=300000+10;
              int a[N],dp[N],up[N],down[N];
              int h[N],st[N],ans[N];
              
              void real_main(int n){
                  fill(dp,dp+n+1,INT_MAX),dp[0]=0;
                  for(int i=1;i<=n;++i){
                      read(a[i]);
                      up[i]=lower_bound(dp+1,dp+n+1,a[i])-dp;
                      dp[up[i]]=a[i];
                  }
                  fill(dp,dp+n+1,INT_MAX),dp[0]=0;
                  for(int i=n;i;--i){
                      down[i]=lower_bound(dp+1,dp+n+1,a[i])-dp;
                      dp[down[i]]=a[i];
                  }
                  // minimum lexicographic order
                  int tot=0;
                  int peak=1,height=up[1]+down[1];
                  for(int i=2;i<=n;++i)
                      if(up[i]+down[i]>height) peak=i,height=up[i]+down[i];
                  int top=0;
                  h[up[peak]]=a[peak];
                  for(int i=peak-1;i;--i){
                      if(a[i]>=h[up[i]+1]) continue;
                      while(top and up[i]>=up[st[top]]) --top;
                      st[++top]=i;
                      h[up[i]]=a[i];
                  }
                  for(;top;--top) ans[++tot]=st[top];
                  ans[++tot]=peak;
                  for(int i=peak+1;i<=n;++i)
                      if(down[i]==down[ans[tot]]-1 and a[i]<a[ans[tot]]) ans[++tot]=i;
                  for(int i=1;i<=tot;++i) printf("%d%c",ans[i]," \n"[i==tot]);
                  // maximum lexcographic order
                  tot=0;
                  peak=1,height=up[1]+down[1];
                  for(int i=2;i<=n;++i)
                      if(up[i]+down[i]>=height) peak=i,height=up[i]+down[i];
                  top=0;
                  st[++top]=peak;
                  for(int i=peak-1;i;--i)
                      if(up[i]==up[st[top]]-1 and a[i]<a[st[top]]) st[++top]=i;
                  for(;top;--top) ans[++tot]=st[top];
                  h[down[peak]]=a[peak];
                  for(int i=peak+1;i<=n;++i){
                      if(a[i]>=h[down[i]+1]) continue;
                      while(tot and down[i]>=down[ans[tot]]) --tot;
                      ans[++tot]=i;
                      h[down[i]]=a[i];
                  }
                  for(int i=1;i<=tot;++i) printf("%d%c",ans[i]," \n"[i==tot]);
              }
              int main(){
                  for(int n;~scanf("%d",&n);) real_main(n);
                  return 0;
              }

              HDU什么时候开始支持<bits/stdc++.h>了……

              相关文章
              相关标签/搜索
              2019年所有开马的记录 大连市| 台北市| 图木舒克市| 平遥县| 淳化县| 靖安县| 潜江市| 荥阳市| 英山县| 石城县| 秭归县| 平乐县| 东山县| 社旗县| 大化| 宁明县| 兴安盟| 六枝特区| 合肥市| 双牌县| 鹤峰县| 平武县| 托里县| 涿鹿县| 阿合奇县| 仲巴县| 金阳县| 衡阳县| 澎湖县| 景谷| 青州市| 安岳县| 连江县| 旅游| 兰考县| 萨迦县| 长汀县| http://fa.hz0j2r3vo.fun http://fa.hz0j2r4vo.fun http://fa.hz0j1r4vo.fun http://fa.hz0j2r1vo.fun http://fa.hz0j0r6vo.fun