zoukankan      html  css  js  c++  java
  • BZOJ4970 : [ioi2004]empodia 障碍段

    通过两遍单调栈求出每个点作为最小值往右延伸到$g[i]$,作为最大值往左延伸到$f[i]$。

    那么一个区间$[i,j]$可行当且仅当$g[i]geq j$、$f[j]leq i$且$i-a[i]==j-a[j]$。

    按$i-a[i]$分组,从左往右考虑每个点作为$j$。

    维护一个$g$单调递减的栈,那么最优的$i$只可能是栈顶。

    如此求出所有固定右端点可能的最优左端点后,贪心求出所有极短合法区间即可。

    时间复杂度$O(n)$。

    #include<cstdio>
    const int N=1100010,BUF=N*10;
    char Buf[BUF],*buf=Buf;
    inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
    int n,m,i,j,a[N],t,q[N],f[N],g[N],st[N*2],nxt[N],p[N],w[N],ans;
    inline void add(int x,int y){nxt[y]=st[x];st[x]=y;}
    inline void solve(){
      if(m<2)return;
      int i;
      for(t=0,i=1;i<=m;i++){
        int x=p[i];
        while(t&&g[q[t]]<x)t--;
        if(t&&q[t]>=f[x])w[x]=q[t];
        while(t&&g[q[t]]<=g[x])t--;
        q[++t]=x;
      }
    }
    int main(){
      fread(Buf,1,BUF,stdin);read(n);
      for(i=1;i<=n;i++)read(a[i]);
      for(i=1;i<=n;q[++t]=i++){
        while(t&&a[q[t]]<a[i])t--;
        f[i]=q[t]+1;
      }
      for(q[t=0]=n+1,i=n;i;q[++t]=i--){
        while(t&&a[q[t]]>a[i])t--;
        g[i]=q[t]-1;
      }
      for(i=n;i;i--)add(i-a[i]+n,i);
      for(i=0;i<=n+n;i++){
        for(m=0,j=st[i];j;j=nxt[j])p[++m]=j;
        solve();
      }
      for(i=1,j=0;i<=n;i++)if(w[i])if(w[i]<=j)w[i]=0;else j=w[i],ans++;
      printf("%d
    ",ans);
      for(i=1;i<=n;i++)if(w[i])printf("%d %d
    ",w[i],i);
      return 0;
    }
    

      

  • 相关阅读:
    TCP_UCP通信原理及案例
    JavaScript高级笔记DOM与BOM
    JavaScript基本语法,基本对象,正则表达式
    JDBC连接池&JDBCTemplate&Sping JDBC
    JDBC,JDBCUtils,JDBC控制事务
    自动化工具ansible(0——准备部署工作)
    监控软件篇——prometheus+exporter组件+grafana
    命令工具篇
    sed 命令备忘
    ES6数据分组
  • 原文地址:https://www.cnblogs.com/clrs97/p/7546920.html
Copyright © 2011-2022 走看看