• BZOJ1107 : [POI2007]驾驶考试egz


    i可以作为起点说明把边反向后可以从1和n到达i。

    设fl[i]表示从1到达i至少需要加几条边,fr[i]表示从n到达i至少需要加几条边。

    把图上下翻转后,从左往右依次计算fl[i],有fl[i]=i-1-左边LIS的长度,用树状数组维护即可$O(nlog n)$求出。

    从右往左计算fr[i]同理。

    然后需要求i,j(i<=j),使得fr[i]+fl[j]<=k。

    由于fl单调递增,fr单调递减,因此随着i不断右移,j也会不断右移,所以可以$O(n)$求出。

    #include<cstdio>
    #define N 100010
    int n,m,p,k,i,j,x,y,z,bit[N],fl[N],fr[N],pre,ans,cnt;
    struct E{int v,f;E*nxt;}*gl[N],*gr[N],pool[N],*cur=pool,*e;
    inline void addl(int x,int y){e=cur++;e->v=y;e->nxt=gl[x];gl[x]=e;}
    inline void addr(int x,int y){e=cur++;e->v=y;e->nxt=gr[x];gr[x]=e;}
    inline void up(int&a,int b){if(a<b)a=b;}
    inline void add(int x,int y){for(;x<=m;x+=x&-x)up(bit[x],y);}
    inline int ask(int x){int t=0;for(;x;x-=x&-x)up(t,bit[x]);return t;}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    int main(){
      read(n),read(m),read(p),read(k);m++;
      while(p--){
        read(x),read(y),read(z);y=m-y;
        z?addl(x+1,y):addr(x,y);
      }
      for(i=2;i<=n;i++){
        for(e=gl[i];e;e=e->nxt)up(pre,e->f=ask(e->v)+1);
        for(e=gl[i];e;e=e->nxt)add(e->v,e->f);
        fl[i]=i-1-pre;
      }
      for(pre=0,i=1;i<=m;i++)bit[i]=0;
      for(i=n-1;i;i--){
        for(e=gr[i];e;e=e->nxt)up(pre,e->f=ask(e->v)+1);
        for(e=gr[i];e;e=e->nxt)add(e->v,e->f);
        fr[i]=n-i-pre;
      }
      for(i=j=1;i<=n;i++){
        while(j<=n&&fr[i]+fl[j]<=k)j++;
        up(ans,j-i);
        if(!fl[i]&&!fr[i])cnt++;
      }
      return printf("%d",ans-cnt),0;
    }
    

      

  • 相关阅读:
    整数反转问题--正确率极低
    May LeetCoding Challenge9 之 求方差
    May LeetCoding Challenge8 之 交叉相乘
    EXCEL上传DEMO
    三层BOM
    OO alv 获取选择列
    PS 项目创建
    读取EXCEL到内表
    SAP XML 到 内表
    BOM 复制功能
  • 原文地址:https://www.cnblogs.com/clrs97/p/4616123.html
Copyright © 2020-2023  润新知