POJ 2481 COWS(树状数组)

题目大意:

  说给你n个线段的,告诉你每个线段的起始点S_i,和终止点E_i, 问这n条线段里有多少线段是相互包含的,如果两个端点重合不算包含。

解题思路:

  用树状数组搞就可以了,这道题是star的变形题,star是让我们求出有多个星星在这个星星的左下角,而这道题是让我们求出有多少个星星在这个星星的左上角。

这样分析,对于(S_i,E_i)我们把他封装成为一个点的坐标,那么(S_j,E_j)同样也可以被封装成为一个点的坐标,而题目中说的S_i<S_j&&E_j<E_i&&E_i-S_i>E_j-S_j就是说j点在i点的左上角,且两点不能重合,好了,有了这个概念,我们只需要对于y按照从大到小排序,对于相同的y我们把x从小到大排序,用树状数组来维护就好了。

代码:

# include<cstdio>
# include<iostream>
# include<fstream>
# include<algorithm>
# include<functional>
# include<cstring>
# include<string>
# include<cstdlib>
# include<iomanip>
# include<numeric>
# include<cctype>
# include<cmath>
# include<ctime>
# include<queue>
# include<stack>
# include<list>
# include<set>
# include<map>

using namespace std;

const double PI=4.0*atan(1.0);

typedef long long LL;
typedef unsigned long long ULL;

# define inf 999999999
# define MAX 100000+4

struct node
{
    int x;
    int y;
    int id;
}a[MAX];

int n;
int ans[MAX];
int tree[MAX];

int cmp ( node a,node b )
{
    if ( a.y!=b.y )
        return a.y > b.y;
    else
        return a.x < b.x;
}

int read ( int pos )
{
    int sum = 0;
    while ( pos > 0 )
    {
        sum+=tree[pos];
        pos -= pos&(-pos);
    }
    return sum;
}


void update ( int pos, int val )
{
    while ( pos <= MAX )
    {
        tree[pos]+=val;
        pos += pos&(-pos);
    }
}


int main(void)
{
    while ( cin>>n )
    {
        memset(tree,0,sizeof(tree));
        memset(ans,0,sizeof(ans));
        if ( n==0 )
            break;

        for ( int i = 0;i < n;i++ )
        {
            scanf("%d %d",&a[i].x,&a[i].y);
            a[i].x++, a[i].y++;
            a[i].id = i;
        }
        sort(a,a+n,cmp);

        ans[a[0].id] = read(a[0].x);
        update(a[0].x,1);
        for ( int i = 1;i < n;i++ )
        {
            if ( a[i].x==a[i-1].x&&a[i].y==a[i-1].y )
            {
                ans[a[i].id]=ans[a[i-1].id];
            }
            else
            {
                ans[a[i].id]=read(a[i].x);
            }
            update(a[i].x,1);
        }
        printf("%d",ans[0]);
        for ( int i = 1;i < n;i++ )
        {
            printf(" %d",ans[i]);
        }
        printf("\n");



    }

    return 0;
}

 

posted @ 2015-04-06 21:01  BYYB_0506  阅读(127)  评论(0编辑  收藏  举报