poj 2481 Cows 树状数组or线段树
题意:
给n个区间,问第i个区间是多少个区间的子区间。
分析:
可以吧每一个线段看成是一个点,这样的话就等价于问一个点的左上方有多少个点?这样就和Stars那题一样了。
因为是求左上方有多少个点,那么把所有点按照y从大到小排列,这样就可以按照顺序求出0~x之间有多少个点,就是它左上方的点了。
需要重点的处理。
树状数组:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
struct point
{
int x,y,id;
}p[N];
bool cmp(const point &a,const point &b)
{
if(a.y==b.y)return a.x<b.x;
return a.y>b.y;
}
int c[N],ans[N];
int lowbit(int x){return x&(-x);}
int getsum(int x)
{
int sum =0;
for(int i=x;i>0;i-=lowbit(i))sum+=c[i];
return sum;
}
void add(int x)
{
for(int i=x;i<N;i+=lowbit(i))c[i]++;
}
int main()
{
int n,x,y;
while(~scanf("%d",&n)&&n){
memset(ans,0,sizeof(ans));
memset(c,0,sizeof(c));
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
++p[i].x; p[i].id=i;
}
sort(p,p+n,cmp);
for(int i=0;i<n;i++){
if(i&&p[i-1].x==p[i].x&&p[i-1].y==p[i].y)ans[p[i].id]=ans[p[i-1].id];
else{
ans[p[i].id]=getsum(p[i].x);
}
add(p[i].x);
}
for(int i=0;i<n-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n-1]);
}
return 0;
}
线段树:
用线段树也是先排序,然后再求区间【0,x】的和,再单点更新。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=1e5+5;
int sum[N<<2];
struct point
{
int x,y,num,ans;
}p[N];
bool cmp(const point &a,const point &b)
{
if(a.y==b.y)return a.x<b.x;
return a.y>b.y;
}
bool cmp2(const point &a,const point &b)
{
return a.num<b.num;
}
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int query(int a,int b,int l,int r,int rt)
{
if(a<=l&&r<=b)return sum[rt];
int m=(l+r)>>1;
int ans=0;
if(a<=m)ans=query(a,b,lson);
if(b>m)ans+=query(a,b,rson);
return ans;
}
void update(int x,int l,int r,int rt)
{
if(l==r){sum[rt]++;return;}
int m=(l+r)>>1;
if(x<=m)update(x,lson);
else update(x,rson);
pushup(rt);
}
int main()
{
int n,x,y;
while(~scanf("%d",&n)&&n){
memset(sum,0,sizeof(sum));
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].x,&p[i].y);p[i].num=i;
}
sort(p,p+n,cmp);
for(int i=0;i<n;i++){
if(i&&p[i].x==p[i-1].x&&p[i].y==p[i-1].y)p[i].ans=p[i-1].ans;
else p[i].ans=query(0,p[i].x,0,1e5,1);
// printf("%d ",p[i].ans);
update(p[i].x,0,1e5,1);
}
sort(p,p+n,cmp2);
for(int i=0;i<n-1;i++){
printf("%d ",p[i].ans);
}
printf("%d\n",p[n-1].ans);
}
return 0;
}