水题一道

题意稍微翻译下:

N个人,每个人有到的时间和离开的时间,如果在一个人到了公司并且还未离开的这段时间里有其他人来,其他人就会对这个人说How are you?

其实看看样例就懂,用什么google翻译

一开始我眼瞎,只看到这个...

只觉得N^2不就随便A吗??

然后喜闻乐见

这才看到N是10^5

咳咳

下面讲讲nlogn的正解

先认真分析一下,一个人只有还待在公司时才能被其他人问候

转换成代码大概就是

    s[i].st<=s[j].st&&s[i].ed>=s[j].st

可以看到,对于j而言,比较的都只是st(到的时间)

所以这里很容易想到将st从小到大排序.

之后再如同n^2算法一样开两层循环,不过第二层循环可以多一个break

代码如下

    for(rg int i=1;i<=n;++i)
    {
        for(rg int j=i+1;j<=n;++j)
        {
            if(s[j].st>s[i].ed) break;
            if(s[j].st<=s[i].ed) ++s[i].num;    
        }
    }

对于当前的第j个人而言,如果他到公司的时候第i个人已经离开了,那么他之后的人都比他还晚到公司,当然就没有必要进行比较.

这就是对n^2算法的一个小优化,然而还是不能过这个题

进一步思考我们可以发现,这里的st很明显满足局部舍弃性.也就是说如果对于第j个人而言都不能满足i,那么j之后的也一定不能满足.

至此,我们就可以使用二分来对最大j的值进行判断

代码如下

    for(rg int i=1;i<=n;++i)
    {
        int ans=i;
        int l=i,r=n;
        if(s[i+1].st>s[i].ed) continue;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(s[mid].st<=s[i].ed)
            {
                ans=mid;
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
        s[i].num+=(ans-i);
    }

最外层1~n,二分时间复杂度logn

总体复杂度nlogn.

本题主要算法介绍到此结束,其余细节就不多解释了.主要是我懒

下面是ac代码(码风丑请轻喷)

#include<bits/stdc++.h>
using namespace std;
#define rg register
#define ll long long
#define maxn 300000 
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
        {
            f=-1;
        }
        c=getchar();
    } 
    while(c<='9'&&c>='0')
    {
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
inline void print(ll x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>=10)
    {
        print(x/10);
    }
    putchar(x%10+'0');
}
int n;
struct node
{
    int st,ed,num,id;
}s[maxn];
inline bool cmp(node a,node b)
{
    if(a.st==b.st) 
    {
        return a.ed<b.ed;
    }
    else return a.st<b.st;
}
inline bool Cmp(node a,node b)
{
    return a.id<b.id;
}
int main()
{
    n=read();
    for(rg int i=1;i<=n;++i)
    {
        s[i].st=read();
        s[i].ed=read();
        s[i].id=i;
    }
    sort(s+1,s+1+n,cmp);
    for(rg int i=1;i<=n;++i)
    {
        int ans=i;
        int l=i,r=n;
        if(s[i+1].st>s[i].ed) continue;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(s[mid].st<=s[i].ed)
            {
                ans=mid;
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
        s[i].num+=(ans-i);
    }
    sort(s+1,s+1+n,Cmp);
    for(rg int i=1;i<=n;++i)
    {
        print(s[i].num);
        putchar('\n');
    }
}