zoukankan      html  css  js  c++  java
  • 解题:POI 2007 Driving Exam

    题面

    有点意思的题

    从一个位置$i$出发可以到达每一个位置即是从$1,n$出发可以到达$i$。然后有了一个做法:把图上下反转后建反图,这样就可以求从一个点$i$到达左右两侧的花费$dp[i][0/1]$了,这个花费就是当前总长度-到这个点为止的LIS长度(左右各求一遍)。因为还要考虑边的这个问题,可以用一个权值树状数组维护前/后缀最大值来实现。可以发现合法点的左侧都能到达左端,右侧都能到达右端,所以其实我们找的是一段区间,即找一段区间$(l,r)$使得$dp[l][1]+dp[r][0]<=k$,发现$dp$数组两维都是单调的,直接双指针即可。

     1 #include<cstdio>
     2 #include<vector>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=100005;
     7 struct a{int h,v;}; vector<a> m1[N],m2[N]; 
     8 int n,m,d,k,t1,t2,typ,len,ans,p1,p2;
     9 int tr[N],dp[N][2];
    10 void maxx(int pos,int num)
    11 {
    12     while(pos<=m)
    13         tr[pos]=max(tr[pos],num),pos+=pos&-pos;
    14 }
    15 int query(int pos)
    16 {
    17     int ret=0;
    18     while(pos)
    19         ret=max(ret,tr[pos]),pos-=pos&-pos;
    20     return ret;
    21 }
    22 int main ()
    23 {
    24     scanf("%d%d%d%d",&n,&m,&d,&k),m++;
    25     for(int i=1;i<=d;i++)
    26     {
    27         scanf("%d%d%d",&t1,&t2,&typ);
    28         if(typ) m1[t1+1].push_back((a){m-t2,0});
    29         else m2[t1].push_back((a){m-t2,0});
    30     }
    31     for(int i=1;i<=n;i++)
    32     {
    33         int siz=m1[i].size();
    34         for(int j=0;j<siz;j++)
    35         {
    36             m1[i][j].v=query(m1[i][j].h)+1;
    37             len=max(len,m1[i][j].v);
    38         }
    39         dp[i][0]=i-len-1;
    40         for(int j=0;j<siz;j++)
    41             maxx(m1[i][j].h,m1[i][j].v);
    42     }
    43     len=0,memset(tr,0,sizeof tr);
    44     for(int i=n;i;i--)
    45     {
    46         int siz=m2[i].size();
    47         for(int j=0;j<siz;j++)
    48         {
    49             m2[i][j].v=query(m2[i][j].h)+1;
    50             len=max(len,m2[i][j].v);
    51         }
    52         dp[i][1]=n-len-i;
    53         for(int j=0;j<siz;j++)
    54             maxx(m2[i][j].h,m2[i][j].v);
    55     }
    56     len=0,p1=p2=1;
    57     while(p1<=n)
    58     {
    59         while(p2<=n&&dp[p1][1]+dp[p2][0]<=k) p2++;
    60         ans=max(ans,p2-p1); if(!dp[p1][0]&&!dp[p1][1]) len++; p1++;
    61     }
    62     printf("%d",ans-len);
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    [转]PHP如何关闭notice级别的错误提示
    [原]php远程odbc连接sqlsvr数据库,自定义端口,命名实例的连接方式
    [原] wmic: Invalid XSL format (or) file name错误解决方法
    [转]PHP Session的一个警告
    [转]权限问题导致Nginx 403 Forbidden错误的解决方法
    [转]require(),include(),require_once()和include_once()区别
    [转]Mysql命令行常用操作
    php读取sql2000的image字段,被截断的问题
    一、基于hadoop的nginx访问日志分析---解析日志篇
    shell判断条件整理
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/9756228.html
Copyright © 2011-2022 走看看