2481 Cows 树状数组 求一段区间被几段区间覆盖的问题

Cows
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 5104 Accepted: 1596

Description

Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good.

Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John's N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E].

But some cows are strong and some are weak. Given two cows: cow i and cow j, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cow i is stronger than cow j.

For each cow, how many cows are stronger than her? Farmer John needs your help!

Input

The input contains multiple test cases.
For each test case, the first line is an integer N (1 <= N <= 10 5), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 10 5) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge.

The end of the input contains a single 0.

Output

For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cow i.

Sample Input

3
1 2
0 3
3 4
0

Sample Output

1 0 0

Hint

Huge input and output,scanf and printf is recommended.

Source

POJ Contest,Author:Mathematica@ZSU
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
    int x,y,tag;//x是左区间,y是右区间, tag是区间号
};   
node cow[100010];
int n;//树状数组大小
int c[100010],ans[100010];
bool cmp(node a,node b)
{
    if(a.y!=b.y) return a.y>b.y;
    return a.x<b.x;
}   
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int val)
{
    for(int i=x;i<=n;i+=lowbit(i))
    {
        c[i]+=val;
    }
}
int getsum(int x)
{
    int cnt=0;
    for(int i=x;i>=1;i-=lowbit(i))  
    {
        cnt+=c[i];
    }
    return cnt;
}               
int main()
{
    int m;//区间个数
    while(scanf("%d",&m)==1&&m)
    {
        n=-1;
        memset(c,0,sizeof(c));//树状数组
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&cow[i].x,&cow[i].y);
            cow[i].x++,cow[i].y++;//树状数组从1开始
            if(cow[i].x>n) n=cow[i].x;
            cow[i].tag=i;
        }   
        sort(cow+1,cow+m+1,cmp);
        ans[cow[1].tag]=0;
        update(cow[1].x,1);
        for(int i=2;i<=m;i++)
        {
            if(cow[i].x==cow[i-1].x&&cow[i].y==cow[i-1].y) ans[cow[i].tag]=ans[cow[i-1].tag];//相等不算覆盖
            else  ans[cow[i].tag]=getsum(cow[i].x);
            update(cow[i].x,1);
        }
        printf("%d",ans[1]);
        for(int i=2;i<=m;i++) printf(" %d",ans[i]);printf("/n");
    }
    return 0;
}     
/*
    说下思路吧,这个题要求的是一个区间要包含在多少个出现的区间。允许边界重复,但是区间长度差值不为0
才可以做计数,测试数据中也有区间相同的输入。用每一个去比较是很容易超时的,先排序,然后用树状数
组做统计。排序的目的在于排在后面的区间的一端(这里用y作为主关键字降序)一定都包含在之前的区间,
或者两个区间相同。要是用y作为主关键字降序排列,如果y相同就用x的升序排序。这样就只有两种情况,
要么当前的区间与前一个区间完全相同,若不是就统计。并且每次都把x坐标加到树状数组中。
    为什么可以这样统计,首先,y坐标是降序的,也就是当前的y肯定比之前的都小(因为区间相同时没有求和,
这里只考虑不一样时候的求和),如果它的横坐标比之前的某个横坐标相同或者大,它就满足包含在那些区间,
就可以做求和,而树状数组的求和正好是顺着树求下去的,而且加上当前的值。这就正好符题意。每次都把当
前的横坐标加到树状数组里就够了,Add函数里加的值是1,因为每次都只有一个区间加进来。
*/     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值