zoukankan      html  css  js  c++  java
  • bzoj1107: [POI2007]驾驶考试egz LIS+单调队列

    Description

      成都的驾驶考试在一个有n条平行的自南向北的单向的道路的场地中进行。每条道路长度为m米,并且都在同一
    条水平线上开始和结束。街道从西向东分别编号为1到n。同样有p条单向的自西向东或自东向西的街道垂直于上面
    描述的街道,每一条这样的街道链接了两个相邻的自南向北的道路。当然自西向东和自东向西的道路可以重叠,那
    就是一个双向的街道了。
      考生选择一个自南向北的道路作为他考试的起始点和另外一个自南向北的道路作为他考试的终止点。他们的考
    试项目是将车从开始的道路驾驶到作为终止点的道路。考生们总是选择一个可以到达所有其他街道的起始道路作为
    开始点。现在,考生们总是感到十分无趣因为他们只有很少的起始道路可以选择,所以教练们决定改造先有的考试
    场所,由于经费的限制,他们决定添加至多K条东西向的道路,使得能够选择的起始道路尽量地多。

    Input

      输入第一行包含四个整数n,m,p和k(2<=n<=100000, 1<=m,k<=100000, 0<=p<=100000)。分别表示南北向的道
    路数,南北向道路的长度,东西向的道路数和最多能够添加的道路数。接下来p行,每行包含三个整数ni,mi和di(1
    < = ni < n,0 < = mi < m,di = 0 or 1),表示一条自西向东(di = 0)或者自东向西(di = 1)的道路。这
    个道路连接了南北向的道路ni和ni+1,在第mi米的地方进行了连接。

    Output

      输出中仅包含一个整数,最大的能够作为起点的道路数(不包括原来就能作为起点的道路数)。注意添加的道
    路不能与南北向的道路相交,并且到起始水平线的距离为整数。添加的道路可以重叠,表示双向的道路。

    题解

    首先前部分讲的超棒的题解:https://blog.csdn.net/wang3312362136/article/details/80017011
    然后我用的单调队列维护的前面已经维护过的道路的边权,但是注意,每次指针要指向队列的最后一个,才能保证答案一定最优。
    最后用(sum)数组记前(i)个数有多少个是原来就是可以作为起点的道路,(sum[j]-sum[i-1])就是(i-j)区间内本身就是起点的个数,接着双指针统计(i-j)区间的答案的最大值。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=1e5+10;
    const int INF=0x3f3f3f3f;
    int n,m,p,k;
    vector<int>ld[maxn];
    vector<int>rd[maxn];
    int q[maxn],sum[maxn];
    int l[maxn],r[maxn];
    int main(){
        // freopen("1107.in","r",stdin);
        // freopen("1107.out","w",stdout);
        ios::sync_with_stdio(false);
        cin>>n>>m>>p>>k;
        for(int i=1;i<=p;i++){
            int x,w,opt;
            cin>>x>>w>>opt;
            if(opt==1) ld[x+1].push_back(w);
            else rd[x].push_back(w);
        }
        ld[1].push_back(INF);
        rd[n].push_back(INF);
        for(int i=1;i<=n;i++){
            sort(ld[i].begin(),ld[i].end());
            sort(rd[i].begin(),rd[i].end());
        }
        int cnt=0,pos=1;
        for(int i=1;i<=n;i++){
            for(int j=0;j<ld[i].size();j++){
                if(!cnt)q[++cnt]=ld[i][j];
                else{
                    pos=cnt;
                    while(pos&&q[pos]<ld[i][j])pos--;
                    q[++pos]=ld[i][j];
                    cnt=max(cnt,pos);
                }
            }
            l[i]=i-cnt;
        }
        cnt=0,pos=1;
        for(int i=n;i>=1;i--){
            for(int j=0;j<rd[i].size();j++){
                if(!cnt)q[++cnt]=rd[i][j];
                else{
                    pos=cnt;
                    while(pos&&q[pos]<rd[i][j])pos--;
                    q[++pos]=rd[i][j];
                    cnt=max(cnt,pos);
                }
            }
            r[i]=n-i+1-cnt;
        }
        for(int i=1;i<=n;i++){
            if(l[i]+r[i]==0)sum[i]++;
            sum[i]=sum[i]+sum[i-1];
        }
        int ans=0;
        for(int i=1,j=1;i<=n&&j<=n;i++){
            while(j<n&&l[j+1]+r[i]<=k)j++;
            if(l[j]+r[i]>k&&i==j){j++;continue;}
            ans=max(ans,j-i+1-sum[j]-sum[i-1]);
        }
        cout<<ans<<endl;
    }
    
  • 相关阅读:
    python chunk 方式读取大文件——本质上还是file read自身支持
    将tflearn的模型保存为pb,给TensorFlow使用
    将TensorFlow模型变为pb——官方本身提供API,直接调用即可
    Ubuntu17.10 下配置caffe 仅CPU i386可以直接apt install caffe-cpu,但是怎么运行mnist代码我懵逼了
    tflearn中计算混淆矩阵方法——需要经过一步转换
    词袋模型 测试数据使用和训练数据一样的词汇表
    借贷宝“自我绑架”:传销式推广只能“烧钱”玩下去?
    借贷宝被看衰 九鼎投资真正意图是什么?
    借贷宝注册送现金疯转 新闻PS图背后真相
    拜读了《婆媳关系好坏取决于老公》一文,看似有道理,细读感觉其实应该不是那么回事
  • 原文地址:https://www.cnblogs.com/Nan-Cheng/p/9833922.html
Copyright © 2011-2022 走看看