poj2481(二维偏序+树状数组)

题目链接:poj.org/problem?id=2481

题目描述

农夫约翰的牛发现,他的田地里沿着山脊生长的三叶草(我们可以将其视为一维数字线)特别好。

农夫约翰有N头母牛(我们将母牛的编号从1到N)。每位农夫约翰的N头母牛都有她特别喜欢的三叶草范围(这些范围可能重叠)。范围由闭合间隔[S,E]定义。

但是有些母牛很强壮,有些却很弱。给定两个母牛:母牛i和母牛j,它们最喜欢的三叶草范围是[Si,Ei]和[Sj,Ej]。如果Si <= Sj并且Ej <= Ei并且Ei-Si> Ej-Sj,我们说母牛i比母牛j强。

对于每头母牛,有几头母牛比她强?农夫约翰需要您的帮助!

输入项

输入包含多个测试用例。

对于每个测试用例,第一行是整数N(1 <= N <= 10 ^ 5),它是母牛的数量。然后是N行,其第i行包含两个整数:S和E(0 <= S

输入的末尾包含单个0。

输出量

 

对于每个测试用例,输出一行包含n个以空格分隔的整数,其中第i个数字指定比母牛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.

 

题目大意 

给你一些区间,对每个区间进行询问,查找所有区间中能包含当前区间的个数。

题解

二维偏序问题,我们可以对区间按照 s 从小到大排序,s相等则按照 e 从大到小排序。这样可以使得后面的区间的起点一定大于前面的,因此我们就不用考虑s了,只需要考虑e就行了。

之后我们维护一个树状数组记录一段区间内小于当前e的区间个数,然后我们求出已经插入所有的区间个数,减去小于的,剩下的就是大于等于当前e的区间个数。

不过这个题有个trick,就是区间相同的情况,这里我们可以记录下来有多少个相同的,直接一次插入完。

 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PI atan(1.0)*4
#define E 2.718281828
#define rp(i,s,t) for (i = (s); i <= (t); i++)
#define RP(i,s,t) for (i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define push_back() pb()
#define fastIn                    \
    ios_base::sync_with_stdio(0); \
    cin.tie(0);
using namespace std;
inline int read()
{
    int a=0,b=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
            b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        a=(a<<3)+(a<<1)+c-'0';
        c=getchar();
    }
    return a*b;
}
inline void write(int n)
{
    if(n<0)
    {
        putchar('-');
        n=-n;
    }
    if(n>=10)
        write(n/10);
    putchar(n%10+'0');
}
const int N = 1e5+7;
int c[N+2],res[N+2],n;
//维护树状数组c为一段区间内的小于当前e的区间个数
//res数组记录询问的结果
struct node{
    int s,e,id;
    bool operator < (const node & others){//按照s从小到大排序,若s相等按照e从大到小排序
        return s==others.s?e>others.e:s0){
        res+=c[i];
        i-=lowbit(i);
    }
    return res;
}
int main(){
    int i,j;
    while(~scanf("%d",&n)){
        if(!n) break;
        mst(c,0);
        rp(i,1,n) p[i].s=read(),p[i].e=read(),p[i].id=i;
        sort(p+1,p+1+n);
        p[0].s=-1;
        rp(i,1,n){
            int m=i,t=1;
            while(m!=n&&p[m+1].e==p[m].e&&p[m+1].s==p[m].s) t++,m++;//找到有多少个相等的区间
            res[p[m].id]=query(N)-query(p[i].e-1);//记录查询结果(即e大于当前e的区间个数),因为查询时是小于等于的,所以需要减 1 
            update(p[i].e,t);//往上更新树状数组c,不过要考虑相等区间,相当于加在一起更新了
            for(;i

 

你可能感兴趣的:(树状数组)