• HDU 5714 拍照 前缀和


    拍照

    题目连接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5714

    Description

    小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行。小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中。

    小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为90度角,只能以垂直于河边的方向进行拍照。河上的船只全都可看作是平行于河边的一条线段,跟河边的距离各不相同,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的。小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况。

    http://acm.hdu.edu.cn/data/images/C715-1003-1.jpg

    Input

    第一行为T,表示输入数据组数。

    下面T组数据,对于每组数据:

    第一行是一个数n(1≤n≤104),表示船只的数量。

    接下来n行,每行四个整数
    x,y,z,d(−106≤x<y≤106,1≤z≤104),表示船只的左端点位置、右端点位置、距离河边的距离,以及航行的方向。d为−1表示向左航行,1表示向右航行。

    Output

    对第i组数据,输出

    Case #i:

    然后输出一行,仅包含一个整数,表示最多可以拍到多少完整的船只。

    Sample Input

    3
    2
    1 3 1 1
    2 4 1 -1
    2
    1 3 1 -1
    2 4 1 1
    1
    1 4 1 1

    Sample Output

    Case #1:
    2
    Case #2:
    1
    Case #3:
    0

    Hint

    题意

    题解:

    分成两个方向去做,在同一个方向的船的相对位置会保持不变,那么我们相当于每条船会给你一个线段

    然后你可以得到线段最大重叠数……

    单方向做完了之后,你会发现,只要r>l,r是向左走的船坐标,l是向右走的船的坐标

    那么肯定在某一时刻,这俩坐标是会重叠的,所以只要记录一个前缀最大值,然后莽一波就好了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+7;
    map<int,int> H;
    int l[maxn],r[maxn],x[maxn],y[maxn],z[maxn],d[maxn];
    vector<int>V;
    int tot,c[maxn],n;
    void init()
    {
        tot=0;
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        H.clear();V.clear();
    }
    void solve(int cas)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&x[i],&y[i],&z[i],&d[i]);
            V.push_back(y[i]-z[i]),V.push_back(x[i]+z[i]+1);
        }
        sort(V.begin(),V.end());
        V.erase(unique(V.begin(),V.end()),V.end());
        for(int i=0;i<V.size();i++)
            H[V[i]]=i+1;
        for(int i=1;i<=n;i++)
        {
            if(y[i]-z[i]<=x[i]+z[i])
            {
                int x1=H[y[i]-z[i]],x2=H[x[i]+z[i]+1];
                if(d[i]==1)l[x1]++,l[x2]--;
                else r[x1]++,r[x2]--;
            }
        }
        int Max = 0,Ans = 0;
        for(int i=1;i<=V.size();i++)
        {
            l[i]+=l[i-1],r[i]+=r[i-1];
            Max=max(Max,l[i]);
            Ans=max(Ans,Max+r[i]);
        }
        printf("Case #%d:
    %d
    ",cas,Ans);
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int i=1;i<=t;i++)
            solve(i);
        return 0;
    }
  • 相关阅读:
    C++指针和引用及区别
    C/C++中extern关键字总结
    php进阶面试题总结
    算法疑难(js实现)---11、字典树
    Trie|如何用字典树实现搜索引擎的关键词提示功能
    ExtJS表格——行号、复选框、选择模型
    Ext.js 中 25种类型的Ext.panel.Tool
    Ext NumberField使用
    [ext]form.submit()相关说明
    ExtJS 表单 submit时错误处理
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5548362.html
Copyright © 2020-2023  润新知