POJ COWS (树状数组)

http://poj.org/problem?id=2481

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: cowi and cowj, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cowiis stronger than cowj. 

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 <= 105), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 105) 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 cowi. 

Sample Input

3
1 2
0 3
3 4
0

Sample Output

1 0 0

题意:

si >= sj && ei >= ej && ei - si > ej - sj, 在区间[s,e]中有多少个区间,这些区间与si,ei最多一个交点

思路:

可以先把这些点按照s升序排列,如果s相同那就按e降序排列,反正就是对于排列完的点除非出现si == sj && ei == ej这种情况,其他的都是si < sj 那么如果ei < ej 那么j对i无贡献,ei>=ej有贡献,即只需要比较e的值即可,可以用树状数组来实现

//
//  main.cpp
//  D - Cows
//
//  Created by dhl on 2018/7/22.
//  Copyright © 2018年 dhl. All rights reserved.
//

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
struct ac {
    int s, e, id;
};
ac a[maxn];

int sum[maxn], c[maxn];
int lowbit(int x) {
    return x&(-x);
}
bool cmp(ac a, ac b) {
    if (a.s == b.s)
        return a.e > b.e;
    return a.s < b.s;
}
void updata(int x) {
    while(x <= maxn) {
        c[x] ++;
        x += lowbit(x);
    }
}
int getsum(int x) {//getsum的意义就是得到前x项的和在本题中就是得到小于x的数量
    int s = 0;
    while(x > 0) {
        s += c[x];
        x -= lowbit(x);
    }
    return s;
}
int main(int argc, const char * argv[]) {
    int n;
    ios::sync_with_stdio(false);
    while(cin >> n, n) {
        memset(sum, 0, sizeof(sum));
        memset(a, 0, sizeof(a));
        memset(c, 0, sizeof(c));
        for (int i = 0; i < n; i ++) {
            cin >> a[i].s >> a[i].e;
            a[i].s ++;
            a[i].e ++;
            a[i].id = i;
        }
        sort(a, a + n, cmp);
        for (int i = 0; i < n; i ++) {
            if (i && a[i].s == a[i - 1].s && a[i].e == a[i - 1].e)
                sum[a[i].id] = sum[a[i - 1].id];
            else {
                int t1 = getsum(maxn);//全部的和
                int t2 = getsum(a[i].e - 1);//小于右端点的数
                sum[a[i].id] = t1 - t2; // 大于等于右端点的数
                //cout << endl << t1 << " " << t2 << endl;
            }
            updata(a[i].e);
        }
        for (int i = 0; i < n; i ++) {
            if (i)
                cout << " ";
            cout << sum[i];
        }
        cout << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/81157028