poj 2481 cows

题目大意:

有一些集合,求每个集合是多少个集合的真子集

思路:

树状数组

先按照右端点从大到小排序,这样只要考虑之前比它左端点小的出现过几次就可以了

模板题

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
int n,c[101010],ans[101010],maxn;
struct data
{
    int s,e,num;
    bool operator < (const data &a) const
    {
        if(e==a.e) return s<a.s;
        return e>a.e;
    }
}inv[101010];
int lowbit(int x){return x&(-x);}
void add(int i) { while(i<=maxn) {c[i]++;i+=lowbit(i);} }
int sum(int i)
{
    int a=0;
    while(i>0) {a+=c[i];i-=lowbit(i);}
    return a;
}
int main()
{
    while(scanf("%d",&n)&&n!=0)
    {
        memset(c,0,sizeof(c));
        maxn=-1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&inv[i].s,&inv[i].e);
            inv[i].s++,inv[i].e++;
            inv[i].num=i;
            maxn=max(maxn,inv[i].e);
        }
        sort(inv+1,inv+n+1);
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(inv[i].e==inv[i-1].e&&inv[i].s==inv[i-1].s) cnt++;
            else cnt=0;
            ans[inv[i].num]=sum(inv[i].s)-cnt;
            add(inv[i].s);
        }
        for(int i=1;i<=n;i++) printf("%d ",ans[i]);
        printf("\n");
    }
}
View Code

 

posted @ 2017-07-23 08:48  jack_yyc  阅读(90)  评论(0编辑  收藏  举报