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;
}

你可能感兴趣的:(poj 2481 Cows 树状数组or线段树)