zoukankan      html  css  js  c++  java
  • COGS2485 从零开始的序列

    传送门

    题意:给定一个长为$n$的序列,定义$f(x)$表示所有(长为$x$的区间最小值)的最大值,求$f(1)$~$f(n)$。

    看好多人都用并查集做的,然而我并不想写……既然品酒大会可以后缀数组+并查集也可以直接用后缀树递推,那这个问题直接上树再递推也行吧……

    跟RMQ有关的一个树形结构就是笛卡尔树,那么我们构建笛卡尔树后自底向上递推一遍即可,对每个节点更新它对应区间长度的答案,最后根据$f(x)ge f(x+1)$更新一遍所有的$f$即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=200010;
     6 void bfs();
     7 int n,a[maxn],f[maxn],root,lc[maxn]={0},rc[maxn]={0},s[maxn],top=0,q[maxn],size[maxn]={0};
     8 int main(){
     9     freopen("sky_seq.in","r",stdin);
    10     freopen("sky_seq.out","w",stdout);
    11     memset(f,-63,sizeof(f));
    12     scanf("%d",&n);
    13     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    14     s[++top]=root=1;
    15     for(int i=2;i<=n;i++){
    16         s[top+1]=0;
    17         while(a[i]<a[s[top]])top--;
    18         if(top)rc[s[top]]=i;
    19         else root=i;
    20         lc[i]=s[top+1];
    21         s[++top]=i;
    22     }
    23     bfs();
    24     for(int i=n;i;i--)f[i]=max(f[i],f[i+1]);
    25     for(int i=1;i<=n;i++)printf("%d ",f[i]);
    26     return 0;
    27 }
    28 void bfs(){
    29     int x,head=1,tail=1;
    30     q[tail++]=root;
    31     while(head!=tail){
    32         x=q[head++];
    33         size[x]=1;
    34         if(lc[x])q[tail++]=lc[x];
    35         if(rc[x])q[tail++]=rc[x];
    36     }
    37     for(int i=n;i;i--){
    38         x=q[i];
    39         size[x]+=size[lc[x]]+size[rc[x]];
    40         f[size[x]]=max(f[size[x]],a[x]);
    41     }
    42 }
    View Code

    lyc说这个题是从CF上搬过来的,然而他也忘了是哪道题了……麻烦知道的dalao在评论里告诉我一声……

  • 相关阅读:
    解决Eclipse中文乱码
    C++中set用法回顾
    二分查找题目汇总
    给网卡配置多个IP地址(win/linux)
    route在windows与liunx下的使用区别
    eclipse 编程 c++ 快捷键
    Git、GitHub、GitLab三者之间的联系以及区别
    SQL语句优化
    《领域驱动设计的原则与实践》读书笔记(一)
    DotNet Core 介绍
  • 原文地址:https://www.cnblogs.com/hzoier/p/6488703.html
Copyright © 2011-2022 走看看