poj 2481 Cows(树状数组)

博客围绕牛的强壮判断问题展开,给定牛喜爱范围【S,Ei】,若一头牛的S小于等于另一头牛且E大于等于另一头牛,且S和E不同时相等,则更强壮。通过对E从大到小排序,利用树状数组判断下界,还给出处理区间相同情况的方法,同时提到输入范围调整。

题目链接:点击打开链接


题意:山坡上长满三叶草,给定一群牛和他们喜爱的范围【S,Ei】,如果一头牛的S小于等于另一头牛而E大于等于另一头牛的,且S和E不同时相等,那么这头牛就比另一头牛强壮。


可以先对E从大到小排序,这样保证遍历时后出现的牛的上界一定满足小于等于前面的,这样只需要判断他的下界满不满足就行,这就想到了用树状数组。

用树状数组c[i]保存到 i 前有多少牛的下界判断过了。

这样对每个牛先把他的下界加进去,再查有多少小于他的下界的牛,答案就是这个数-1(减他自己)


对于判断S和E不同时相等有一个好的办法,就是添加完后先判断当前区间是否和前一个区间完全相同,如果相同就直接让答案等于前一个区间的。因为区间完全相同的一定排在一起且答案相同,这样当第一个加进去的时候此时除他自己以外没有别的妞区间和他完全相同,按上面的算法得到正确的答案,后面每一个就复制他的答案即可。


本题范围是从零开始,直接输入0会在query时引起死循环,所以输入时全部+1


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 100010
using namespace std;
struct cow{
    int s,e,id;
    bool operator ==(cow obj){
        return s==obj.s&&e==obj.e;
    }
}a[MAX];
int res[MAX];
bool cmp(cow a,cow b){
    return a.e>b.e||(a.e==b.e&&a.s<b.s);
}
int c[MAX];
int N;
int lowbit(int n){
    return n&(-n);
}

void add(int n,int p){
    while(p<=MAX) {
        c[p]+=n;
        p+=lowbit(p);
    }
}

int query(int p){
    int res=0;
    while(p>0){
        res+=c[p];
        p-=lowbit(p);
    }
    return res;
}

int main(){
    while(~scanf("%d",&N)){
        memset(c,0,sizeof(c));
        if(!N) break;
        for(int i=1;i<=N;i++){
            scanf("%d%d",&a[i].s,&a[i].e);
            a[i].id=i;
        }
        sort(a+1,a+N+1,cmp);
        for(int i=1;i<=N;i++){
            add(1,a[i].s+1);
            if(a[i]==a[i-1]){
                res[a[i].id]=res[a[i-1].id];
            }
            else{
               res[a[i].id]=query(a[i].s+1)-1;
            }
        }
        for(int i=1;i<N;i++){
            printf("%d ",res[i]);
        }
        printf("%d\n",res[N]);
    }
    return 0;
}



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值