您的位置:首页 > 其它

poj2481 Cows

2018-01-28 14:54 148 查看

Cows

Time Limit: 3000MSMemory Limit: 65536K
Total Submissions: 20652Accepted: 7019
DescriptionFarmer 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 cowi is stronger than cowj.

For each cow, how many cows are stronger than her? Farmer John needs your help!InputThe 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.OutputFor 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 Input3
1 2
0 3
3 4
0
Sample Output1 0 0
HintHuge input and output,scanf and printf is recommended.

题目描述

这是一道树状数组题目,如果对树状数组不太熟悉,可以参考树状数组

对于cow_i对应一个区间[S_i,E_i],对于cow_i和cow_j如果满足S_i≤S_j and E_i≥E_j,则称cow_i比cow_j强壮,对于一个给定的cow_i,给出共有多少个比cow_i强壮的牛。

算法设计

首先需要明确一点,这个题目是离线的而不是在线的,所以一开始对于输入进行排序,排序之前需要记录该牛的编号,所以对于该牛可以使用以下结构进行储存,并重写比较函数。

struct cow{
int s,e,position;
bool operator <(const cow a){
if(a.e == e){
return a.s > s;
}
else{
return a.e < e;
}
}
}


排序完成后可以根据排序来进行统计,如果排序之后的牛与前面相邻的牛具有相同的[S_i,E_i],则直接记前面相邻牛对应的数量即可,否则使用sum函数进行统计,每次都需要使用update进行更新,直到遍历完成,此时即可获得所有的比任意一个牛强壮的牛的数量。伪代码如下:

for i = 1 to n
if(input[i].e == input[i-1].e && input[i].s == input[i-1].s){
res[input[i].position] = res[input[i-1].position];
}
else{
res[input[i].position] = sum(input[i].s+1);
}
update(input[i].s+1,1);


代码实现

#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX = 100010;
int BIT[MAX],res[MAX];
int lowBit(int i);
void update(int index,int delta);
int sum(int index);
struct cow{ int s,e,position; bool operator <(const cow a){ if(a.e == e){ return a.s > s; } else{ return a.e < e; } } }input[MAX];
int main(){
int n;
while(scanf("%d",&n)){
if(n == 0){
break;
}
memset(BIT,0,sizeof(BIT));
memset(res,0,sizeof(res));
for(int i = 1;i <= n;i ++){
scanf("%d%d",&input[i].s,&input[i].e);
input[i].position = i;
}
sort(input+1,input+n+1);
for(int i = 1;i <= n;i ++){
if(input[i].e == input[i-1].e && input[i].s == input[i-1].s){
res[input[i].position] = res[input[i-1].position];
}
else{
res[input[i].position] = sum(input[i].s+1);
}
update(input[i].s+1,1);
}
for(int i = 1;i <= n;i ++){
if(i == n){
printf("%d\n",res[i]);
}
else{
printf("%d ",res[i]);
}
}
}
return 0;
}
int lowBit(int i){
return i & (-i);
}
int sum(int index){
int res = 0;
for(int i = index;i > 0;i -= lowBit(i)){
res += BIT[i];
}
return res;
}
void update(int index,int delta){
for(int i = index;i <= MAX;i += lowBit(i)){
BIT[i] += delta;
}
}


复杂度分析

初始化输入时间复杂度为O(n),对每一个元素进行查询每一次为O(log⁡〖n)〗,一共n次,所以时间复杂度为(O(n log⁡〖n)〗,由于只是增添了一个辅助数组,所以空间复杂度仍为O(n)。

编程技巧

本问题仍不能直接使用序号进行区间查询,所以还是需要建立一个序号到支持区间查询序号之间的一对一映射来完成该操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: