• 【Ural1028】Stars-线段树和树状数组入门题


    题目大意:一个平面上有若干个点,规定每个点的等级为在它左下的点的个数(包括正左和正下),求出各等级的点的数目。输入时这些点的Y坐标按升序排列,Y坐标相同时X坐标按升序排列。

    做法:题目中输入数据的顺序提示了我们要如何处理。当我们要处理一个点时,求出在它之前插入的在它左边的(X坐标比它小的)点的数目,又由于Y坐标按升序排列,所以这些点又必须在它之下,这就找到了题目中所求的点的个数。题目比较简单,在代码里就不多作注释了。

    以下是本人代码:

    线段树:

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    long n,ans[15010]={0};
    struct node
    {
      long l,r;
      long sum;
    }seg[70010];
    
    void input()
    {
      scanf("%ld",&n);
    }
    
    void output()
    {
      for(int i=0;i<=n-1;i++)
        printf("%ld
    ",ans[i]);
    }
    
    void buildtree(long nodenum,long left,long right)
    {
      seg[nodenum].l=left;seg[nodenum].r=right;
      if (left==right) seg[nodenum].sum=0;
      else
      {
        buildtree(2*nodenum,left,(left+right)/2);
    	buildtree(2*nodenum+1,(left+right)/2+1,right);
    	seg[nodenum].sum=seg[2*nodenum].sum+seg[2*nodenum+1].sum;
      }
    }
    
    void add(long nodenum,long k,long d)
    {
      if (seg[nodenum].l<=k&&seg[nodenum].r>=k)
      {
        seg[nodenum].sum+=d;
    	if (seg[nodenum].l==seg[nodenum].r) return;
    	if (k<=seg[2*nodenum].r) add(2*nodenum,k,d);
    	if (k>=seg[2*nodenum+1].l) add(2*nodenum+1,k,d);
      }
    }
    
    long query(long nodenum,long s,long t)
    {
      if (seg[nodenum].l>=s&&seg[nodenum].r<=t) return seg[nodenum].sum;
      else
      {
        long total=0;
    	if (s<=seg[2*nodenum].r&&t>=seg[2*nodenum].l) total+=query(2*nodenum,s,t);
    	if (s<=seg[2*nodenum+1].r&&t>=seg[2*nodenum+1].l) total+=query(2*nodenum+1,s,t);
        return total;
      }
    }
    
    int main()
    {
      input();
      buildtree(1,0,32000);
      for(int i=1;i<=n;i++)
      {
        long x,y;
        scanf("%ld %ld",&x,&y);
    	add(1,x,1);
    	ans[query(1,0,x)-1]++;
      }
      output();
      
      return 0;
    }
    
    树状数组:

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,c[32010]={0},v[15010]={0};
    
    int lowbit(int i)
    {
      return i&(-i);
    }
    
    void add(int v,int a)
    {
      for(int i=v;i<=32001;i+=lowbit(i))
        c[i]+=a;
    }
    
    int sum(int x)
    {
      int s=0;
      for(int i=x;i>0;i-=lowbit(i))
        s+=c[i];
      return s;
    }
    
    int main()
    {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
      {
        int x,y;
    	scanf("%d %d",&x,&y);
    	v[sum(x+1)]++; //坐标可能为0,不方便处理,所以将其+1
    	add(x+1,1);
      }
      for(int i=0;i<n;i++) printf("%d
    ",v[i]);
      
      return 0;
    }
    



  • 相关阅读:
    AtomicInteger原理分析
    packageinfo.java介绍
    SpringBoot 日志、配置文件、接口数据脱敏
    Gulp自动化构建分析
    RPC本质思考
    ES6 之 let 与 const
    Java属性转换工具分析
    AMQP协议模型及相关组件介绍
    Spring Bean生命周期分析
    PHP 脚本后台执行
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793999.html
Copyright © 2020-2023  润新知