最大重叠事件数的持续时间

时间:2016-03-03 11:12:46

标签: c++ algorithm sorting overlap

在尝试提高我的算法技能的同时,我发现自己陷入了以下问题,简而言之,要求你找到一个房间里有最多人数的时间跨度:

https://jutge.org/problems/P27158_en

我提出的解决方案正确解决了网站建议的所有公共测试用例的问题,但是对于一个或多个隐藏的私有测试用例失败了。

我的解决方案为std :: vector中的每个事件保存两个条目:一个用于到达,一个用于离开,每个条目由[eventtype,eventtime]组成。然后按事件时间对向量进行排序,最后循环遍历向量以确定有最大访客数的时间跨度的持续时间。我的代码如下:

          $(document).ready(function(){
                 $("#owl-demo").owlCarousel({

                        autoPlay: 3000, //Set AutoPlay to 3 seconds
                        responsive: true,
                        loop: true,
                        addClassActive: true,
                        items: 4,
                        stopOnHover:true,
                        afterMove:function(){
                            //console.log(1);
                            $(".owl-item").css({
                                border: 'none',
                            })
                            $(".owl-item").removeClass( "myClass" );
                            $(".active").eq(0).css({
                                border: '2px solid red',

                            })
                            $(".active").eq(0).addClass( "myClass");
                            var myValue = $( ".myClass" ).find('.dd').html();
                            $("#content").html(myValue);

                        },
                        afterInit:function(){
                            $(".active").eq(0).css({
                                border: '2px solid red',
                            })
                            $(".active").eq(0).addClass( "myClass");
                            var myValue = $( ".myClass" ).find('.dd').html();
                            $("#content").html(myValue);
                        }

                    });

          });

我已经相应地修改了@j_random_hacker的注释代码,并且程序现在没有像以前那样对隐藏的私有测试用例超过时间限制,但现在得到判决“错误回答”(仅适用于私有测试)例)。我将尝试找出算法错误可能是什么。谢谢所有回答的人。

2 个答案:

答案 0 :(得分:2)

我将比较功能更改为此并且TLE消失(并更改为WA):

bool operator< ( const Event& e ) const
{
    return (time < e.time) || (time == e.time && type==EventType::LEAVE && e.type != EventType::LEAVE);
}

正如评论中所建议的那样,原因是你给出的比较函数没有strict weak ordering。 (即使两个对象具有相同的true和相同的timetype),它也会返回EventType::LEAVE,而当两个对象都是等效的时,它应该返回false。 )

修改

由于这些测试用例,您正在获得WA:

5 1 3 1 3 3 4 4 7 4 7

您的输出 - 2 6
正确输出 - 2 3

您获得了最大数量的事件,但持续时间错误。

对此的补救措施是在两次迭代中计算答案 在第一次迭代中,我们计算最大事件数 在第二次迭代中,我们使用第一次迭代中获得的结果计算最大持续时间。

正确的代码(几乎与你的相似):

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

enum class EventType {ARRIVE, LEAVE};

struct Event
{
    int time;
    EventType type;

    Event() {}
    Event ( int tm, EventType t ) : time ( tm ), type ( t ) {}
    bool operator< ( const Event& e ) const
    {
        return ( time < e.time ) || ( time == e.time && type == EventType::LEAVE &&
                                      e.type != EventType::LEAVE );
    }
};

int main()
{
    int visits;
    int timeStart, timeEnd;
    int maxVisits, maxDuration, localMaxVisits, localStartTime, localEndTime,
         duration;
    std::vector<Event> events;
    std::vector<Event>::const_iterator it;
    // Get each Case from stdin.
    // 0 is the special stopping case.
    while ( cin >> visits && visits != 0 )
    {
        events.clear();
        // Read all the visits, for each one save two entries to the visits-vector,
        // one for the arrival time another for the leaving time.
        for ( int i = 1; i <= visits; ++i )
        {
            cin >> timeStart >> timeEnd;
            Event eStart ( timeStart, EventType::ARRIVE );
            Event eEnd ( timeEnd, EventType::LEAVE );
            events.push_back ( eStart );
            events.push_back ( eEnd );
        }

        // Sorting the vector so that events are ordered by their arrival time.
        // In case two events coincide on arrival time, we place leaving events before arrival events.
        std::sort ( events.begin(), events.end() );

        maxVisits = 0;
        localMaxVisits = 0;

        // Find `maxVisits`
        for ( it = events.begin(); it != events.end(); ++it )
        {
            if ( ( *it ).type == EventType::ARRIVE )
            {
                localMaxVisits++;
            }
            else
            {
                maxVisits = max ( maxVisits, localMaxVisits );
                localMaxVisits--;
            }
        }


        maxDuration = 0;
        localStartTime = 0;
        localEndTime = 0;

        // Now calculate `maxDuration`
        for ( it = events.begin(); it != events.end(); ++it )
        {
            if ( ( *it ).type == EventType::ARRIVE )
            {
                localMaxVisits++;
                if ( localMaxVisits == maxVisits && localEndTime < ( *it ).time )
                {
                    localStartTime = ( *it ).time;
                }
            }
            else
            {
                duration = ( *it ).time - localStartTime;
                if ( localMaxVisits == maxVisits )
                {
                    localEndTime = ( *it ).time;
                    maxDuration = max ( maxDuration, duration );
                }
                localMaxVisits--;
            }
        }

        cout << maxVisits << " " << maxDuration << endl;
    }
}

答案 1 :(得分:1)

您可以通过完全取消Event类并使用pair<int,int>来简化代码。对按照第一个元素(这将是您的事件时间)排序,然后按第二个元素排序。我建议使用类似于:

的代码填充矢量
    vector<pair<int,int>> v;
    for (int i=0; i<n; i++) { // n events to add
        int a, b;
        cin >> a >> b;            
        v.push_back({a, 1});  // 1 for "enter"
        v.push_back({b, -1}); // -1 for "leave"
    }
    sort(v.begin(), v.end());

如您所见,排序不需要额外的任何定义。它只是工作(tm)。

两个陷阱:

  • 如果我到达t0,而其他人在t0离开,则该党的人数没有变化。
  • 如果很多人在同一时间到达或离开,您应该只重新计算一次辅助变更(如果是0,则完全忽略它,就像之前的陷阱一样)。

我还可以确认,对于这个特殊问题,法官不会接受任何使用复杂结构的答案(我最初试图用map<int, int>来解决它)。只需执行

    map<int,int> m;
    for (int i=0; i<n; i++) { // n events to add
        int a, b;
        cin >> a >> b;            
        m[a]++;  // add 1 party-goer at time a
        m[b]--;  // remove 1 at time b
    }

超出时间限制(即使它自动排序)。因此,即使间隔树非常适合重复间隔查询,它们也不是解决此特定问题的正确工具(仅查询一次)。

为难以捉摸的AC修复代码祝你好运!我可以确认它 可以实现。