题目大意:
现有多个测例,每个测例中给出N段闭区间[si, ei](测例以N = 0结束,1 ≤ N ≤ 10^5),si和ei的范围为[1, 10^5],如果两区间[si, ei]和[sj, ej]满足si ≤ sj且ej ≤ ei且ei - si > ej - sj,则成前一个区间大于后一个区间,现要求对于每个测例,都按输入的顺序输出每个区间的比它大区间的数量。
注释代码:
/*
* Problem ID : POJ 2481 Cows
* Author : Lirx.t.Una
* Language : C
* Run Time : 922 ms
* Run Memory : 2480 KB
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
//区间最大数量
#define MAXN 100000
using namespace std;
struct Intv {//interval,闭区间
int s, e;//区间的左右端点
int id;//区间的id,记录区间的输入顺序
bool//对区间按照右端点从大到小排列,如果右端点相等则按照左端点从小到大排列
operator<(const Intv &oth)
const {
if ( e == oth.e ) return s < oth.s;
return e > oth.e;
}
};
Intv inv[MAXN];//区间
int ans[MAXN];//按照输入顺序存放最终结果,每个区间大于它的区间数量
//对inv排好序后,后一个区间的右端点一定小于等于前一个区间,而根据题目要求,只要找到之前左端点小于等于当前区间的区间数量即可,但是需要分情况讨论
//考虑特殊情况,如果后以区间右端点等于前一区间的右端点,则需要找左端点小于当前区间左端点的区间数量
//但实际上,该如果当前区间左端点也等于前移区间左端点则其ans值和前移区间相同,对于其余情况就直接求左端点小于等于当前区间的数量即可
int c[MAXN + 1];//对区间的s域建立树状数组
int lowbit[MAXN + 1];
int n;//区间数量
void
update(int x) {
while ( x <= n ) {//s域的最大值也是MAXN
c[x]++;
x += lowbit[x];
}
}
int
query(int x) {
int sum;
sum = 0;
while ( x > 0 ) {
sum += c[x];
x -= lowbit[x];
}
return sum;
}
int
main() {
int i;
for ( i = 1; i <= MAXN; i++ ) lowbit[i] = i & -i;
while ( scanf("%d", &n), n ) {
memset(c, 0, sizeof(c));
for ( i = 0; i < n; i++ ) {
inv[i].id = i;
scanf("%d%d", &inv[i].s, &inv[i].e);
inv[i].s++;//树状数组
}
sort(inv, inv + n);
//先处理第一个区间
ans[ inv[0].id ] = 0;
update( inv[0].s );
for ( i = 1; i < n; i++ ) {
//剩下的分情况讨论
if ( inv[i].e == inv[i - 1].e && inv[i].s == inv[i - 1].s )
ans[ inv[i].id ] = ans[ inv[i - 1].id ];
else
ans[ inv[i].id ] = query( inv[i].s );
update( inv[i].s );
}
printf("%d", *ans);
for ( i = 1; i < n; i++ ) printf(" %d", ans[i]);
putchar('\n');
}
return 0;
}
无注释代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define MAXN 100000
using namespace std;
struct Intv {
int s, e;
int id;
bool
operator<(const Intv &oth)
const {
if ( e == oth.e ) return s < oth.s;
return e > oth.e;
}
};
Intv inv[MAXN];
int ans[MAXN];
int c[MAXN + 1];
int lowbit[MAXN + 1];
int n;
void
update(int x) {
while ( x <= n ) {
c[x]++;
x += lowbit[x];
}
}
int
query(int x) {
int sum;
sum = 0;
while ( x > 0 ) {
sum += c[x];
x -= lowbit[x];
}
return sum;
}
int
main() {
int i;
for ( i = 1; i <= MAXN; i++ ) lowbit[i] = i & -i;
while ( scanf("%d", &n), n ) {
memset(c, 0, sizeof(c));
for ( i = 0; i < n; i++ ) {
inv[i].id = i;
scanf("%d%d", &inv[i].s, &inv[i].e);
inv[i].s++;
}
sort(inv, inv + n);
ans[ inv[0].id ] = 0;
update( inv[0].s );
for ( i = 1; i < n; i++ ) {
if ( inv[i].e == inv[i - 1].e && inv[i].s == inv[i - 1].s )
ans[ inv[i].id ] = ans[ inv[i - 1].id ];
else
ans[ inv[i].id ] = query( inv[i].s );
update( inv[i].s );
}
printf("%d", *ans);
for ( i = 1; i < n; i++ ) printf(" %d", ans[i]);
putchar('\n');
}
return 0;
}