题目大意:

给你好多的牛,10^5,然后再告诉你每个牛有一个闭区间,现在定义,如果一个牛a的区间是另一个牛b的区间的子区间,那么就说b就比a更强。显然就是让你求出对于每个牛来说,有多少牛比它更强。

分析:

现在应该就是把所有的区间都加到树状数组里面去,然后查询每个区间范围内有多少个完整的区间。但是要注意,有可能有两个完全相同的区间,那么根据xcx的公平哲学原理以及字母无关性等显然性质可知,这两个牛谁都不比谁强。

思路:

大概就是按照区间左端点坐标的递增顺序给这些区间排个序,然后按照这个顺序一个一个添加。每添加一个,那么找出这个区间的右端点右侧有多少个端点,就可以知道有多少牛比他强了。但是要注意一个
问题就是,这里面有可能有区间完全相同的情况。

相同区间的解决办法:

如果单纯的按照上述方法来做的话,就会把相同区间长度的牛也算在比他强的牛里面。
一开始我想到的处理办法是:对于每一块连续的区间起点的枚举,用book数组记录下他们的区间终点。在枚举下一块
连续的区间起点的时候,清空book数组。但是发现这样做最差的时间复杂度为O(n^2)还是超时了。
另外的办法就是,因为在枚举的时候,如果枚举到几个相同起点的区间的时候,他们的枚举顺序是区间终点从大到小,所以,如果上一个区间和这个区间完全相同,那么s++,如果不相同则s=0;这个s表示的就是连续出现了多少个完全相同的区间。

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>

#define maxn 100500

using namespace std;

struct qujian
{
    int l;
    int r;
    int w;
}cow[maxn];
int tree[maxn]={0};
int n;

bool my_cmp(qujian a,qujian b)
{
    if(a.l==b.l)return a.r>b.r;
    return a.l<b.l;
}

int lowbit(int x)
{
    return x&(-x);
}

void add(int x)
{
    while(x<maxn)
    {
        tree[x]++;
        x+=lowbit(x);
    }
}

int sum(int x)
{
    int s=0;
    while(x>0)
    {
        s+=tree[x];
        x-=lowbit(x);
    }
    return s;
}
int main()
{
    int num[maxn]={0};
    while(scanf("%d",&n))
    {
        memset(tree,0,sizeof(tree));
        memset(num,0,sizeof(num));
        if(n==0)return 0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&cow[i].l,&cow[i].r);
            cow[i].l++;
            cow[i].r++;
            cow[i].w=i;
        }
        sort(cow+1,cow+n+1,my_cmp);
        int s=0; 
        for(int i=1;i<=n;i++)
        {
            num[cow[i].w]=sum(maxn-1)-sum(cow[i].r-1)-s;
            add(cow[i].r);
            if(cow[i].l==cow[i+1].l&&cow[i].r==cow[i+1].r)
            {
                s++;
            }
            else
            {
                s=0;
            }
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d ",num[i]);
        }
        cout<<endl;
    }
}

后注:

本题另外一定要注意区间枚举的顺序,就是相同起点要按照区间终点从大到小枚举。具体实现见my_cmp()函数。