• 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
    ",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
    ",p[n-1].ans);
        }
        return 0;
    }
  • 相关阅读:
    淘宝从几百到千万级并发的十四次架构演进之路!
    19 个强大、有趣、好玩、又装B的 Linux 命令!
    Spring Boot实战:拦截器与过滤器
    初识zookeeper,linux 安装配置zookeeper
    Spring-boot:5分钟整合Dubbo构建分布式服务
    Spring-Boot:6分钟掌握SpringBoot开发
    Dubbo的使用及原理浅析.
    Java消息队列--ActiveMq 初体验
    关于Ubuntu 常用的简单指令
    IBM、HPUX、Solaris不同之处
  • 原文地址:https://www.cnblogs.com/01world/p/5651227.html
Copyright © 2020-2023  润新知