Cows题解
农民约翰的奶牛发现,他田里沿着山脊生长的三叶草(我们可以把它想象成一维的数字线)特别好。
农夫约翰有N头奶牛(我们从1到N对奶牛进行编号)。农夫约翰的N头牛都有一系列她特别喜欢的三叶草(这些范围可能重叠)。范围由闭合区间[S,E]定义。
但是有些牛很强壮,有些牛很虚弱。给定两头奶牛:cowi和cowj,它们最喜欢的三叶草品种是[Si,Ei]和[Sj,Ej]。如果Si<=Sj和Ej<=Ei和Ei-Si>Ej-Sj,我们说cowi比cowj强。
每头牛,有多少头牛比她强壮?农夫约翰需要你的帮助!
输入包含多个测试用例。
对于每个测试用例,第一行是整数N(1<=N<=105),这是奶牛的数量。然后是N行,其中第i行包含两个整数:S和E(0<=S<E<=105),分别指定某些奶牛喜欢的范围的开始-结束位置。位置以距山脊起点的距离表示。
输入的末尾包含一个0。
输出
对于每个测试用例,输出一行包含n个空格分隔的整数,其中第i行指定比cowi更强的奶牛数量。
3
1 2
0 3
3 4
0
1 0 0
就是一个需要自己排序并且去重的数星星(不过顺序从左下跑到了左上,当时只看出了星星)
一开始想的是数星星,左端点抽象成x,右端点抽象成y,那么问题就成了这个点的左上有几点
被GGrun带偏了,以为是一个算包含情况加去重的校门外的树,结果半天想不出来,看的题解,然后看明白了
点击查看代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int c[120000];
int b[120000];
struct node{
int from;
int to;
int id;
}a[120000];
bool operator <(const node&a,const node&b){
if(a.to==b.to) return a.from<b.from;
else return a.to>b.to;
}
int n,m,k;
int lowbit(int x){
return x&-x;
}
void add(int x,int add){
for(int i=x;i<=n;i+=lowbit(i)){
c[i]+=add;
}
}
int sum(int x){
int ans=0;
for(int i=x;i>0;i-=lowbit(i)){
ans+=c[i];
}
return ans;
}
int main(){
while(scanf("%d",&n)!=-1&&n){
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].from,&a[i].to);
a[i].from++;a[i].to++;
a[i].id=i;
}
sort(a+1,a+1+n);
b[a[1].id]=0;
add(a[1].from,1);
for(int i=2;i<=n;i++){
if(a[i].from==a[i-1].from&&a[i].to==a[i-1].to){
b[a[i].id]=b[a[i-1].id];
}
else b[a[i].id]=sum(a[i].from);
add(a[i].from,1);
}
for(int i=1;i<=n;i++){
printf("%d ",b[i]);
}
printf("\n");
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
memset(b,0,sizeof(b));
}
}