POJ2481 Cows

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

我感觉这道题给那个那个差的比较就是坑爹的……我按着差写了大半天结果WA了个各种惨啊……

好吧,这道题是按照权值建立线段树,意思就是把每一个点加入到它应有的大小范围内,线段树上面每一个点维护的是该区间内有多少个点,这样很容易就能查出来比某一个元素大的元素有多少个。而且,还得先对所有的点排序,主排序应该是把s从小到大排序,当s相等的时候,e从大到小排序,这样就必须记录每个元素原来的位置,这样每次插入一个新的元素的时候,在它之前插入的所有的元素s上都是满足条件的,换言之,线段树中只需要维护e的情况就行了。其实……e符合条件了差值自然也就符合条件了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 100100;
struct data{
    int s, e, i;
    friend bool operator < (const data &a, const data &b){
        if (a.s != b.s) return a.s < b.s;
        return a.e > b.e;
    }
}cow[maxn];
int num[maxn << 2], ans[maxn];
void build(int l, int r, int rt){
    num[rt] = 0;
    if (l == r) return;
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
}
void update(int x, int l, int r, int rt){
    num[rt] += 1;
    if (l == r) return;
    int m = (l + r) >> 1;
    if (x <= m) update(x, lson);
    else update(x, rson);
}
int query(int ll, int rr, int l, int r, int rt){
    if (ll <= l && rr >= r) return num[rt];
    int m = (l + r) >> 1;
    int ret = 0;
    if (ll <= m) ret += query(ll, rr, lson);
    if (rr > m) ret += query(ll, rr, rson);
    return ret;
}
int main(){
    int n;
    while (~scanf("%d", &n) && n){
        memset(ans, 0, sizeof(ans));
        int m = 0;
        for (int i = 0; i < n; i++){
            scanf("%d%d", &cow[i].s, &cow[i].e);
            cow[i].s += 1; cow[i].e += 1;
            m = max(cow[i].e, m);
            cow[i].i = i;
        }
        sort(cow, cow + n);
        build (1, m, 1);
        for (int i = 0; i < n; i++){
            if (i && cow[i].s == cow[i - 1].s && cow[i].e == cow[i - 1].e){
                ans[cow[i].i] = ans[cow[i - 1].i];
                update(cow[i].e, 1, m, 1);
            }
            else{
                ans[cow[i].i] = query(cow[i].e, m, 1, m, 1);
                update(cow[i].e, 1, m, 1);
            }
        }
        for (int i = 0; i < n; i++){
            printf("%d", ans[i]);
            if (i != n-1) printf(" ");
            else printf("\n");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值