POJ

来源:互联网 发布:stp真空隔热板 知乎 编辑:程序博客网 时间:2024/06/14 05:58

题目大意:

给你好多的牛,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 100500using 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()函数。

0 0
原创粉丝点击