IndexTree-POJ2352_javaIndexTree-POJ2352_java_02
package Week3;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

//描述
//
//天文学家经常检查恒星地图,其中恒星以平面上的点表示,每颗恒星都有笛卡尔坐标。让恒星的水平成为不高而不是在给定恒星右边的恒星的数量。天文学家想知道恒星水平的分布。
//例如,查看上图上显示的
//地图。5号星的水平等于3(它由三颗星组成,编号为1、2和4)。以2和4为数的恒星水平为1。在这张地图上,只有0级的一颗星,1级的两颗星,2级的一颗星和3级的一颗星。
//您要编写一个程序,该程序将计算给定地图上每个级别的星星
//数量。
//
//输入
//
//输入文件的第一行包含多个星 N (1<=N<=15000)。以下 N 行描述恒星坐标(每行由 0 <+X、Y <=32000 隔开两个整数 X 和 Y)。飞机的某一点只能有一颗星星。星星按Y坐标的上升顺序排列。具有等于 Y 坐标的星星按 X 坐标的升序排列。
//输出
//
//输出应包含 N 行,每行一个数字。第一行包含 0 级的恒星量,第二行包含 1 级的恒星量等,最后一行包含 N-1 级的恒星量。
//示例输入
//
//5
//1 1
//5 1
//7 1
//3 3
//5 5
//样本输出
//
//1
//2
//1
//1
//0

//不散列话做法
//思路y坐标升序,y坐标相等时,x升序
//排完序之后y坐标不管,只看x坐标,处理x坐标表示小于等于x坐标的星星已经被处理tree[e]更新1表示该位置处理元素个数加1
public class POJ2352 {
     static int N;
     static int tree[];//叶子节点表示当前已经处理的星星的个数,tree[1]表示当前处理星星的总的个数,tree上的值表示的x的值大小,第一个叶子节点从0开始
     static int count[];//count[0]表示当前0级星星的个数,count[1]表示当前1级星星的个数,等等
     static int arr[][];
    
     public static void main(String[] args) throws Exception {
        System.setIn(new FileInputStream("Solution.txt"));
         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
         StringTokenizer st = null;
         st = new StringTokenizer(br.readLine());
         N = Integer.parseInt(st.nextToken());
         count = new int[N+1];
         arr = new int[N+1][2];
         int maxX = 0;
         for (int i = 1; i <= N; i++) {
             st = new StringTokenizer(br.readLine());
             int x = Integer.parseInt(st.nextToken());
             int y = Integer.parseInt(st.nextToken());
             arr[i][0]=x;
             arr[i][1]=y;
             maxX = Math.max(x, maxX);
         }
         Arrays.sort(arr, 1, N+1, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1]==o2[1]?o1[0]-o2[0]:o1[1]-o2[1]; //思路y坐标升序,y坐标相等时,x升序
            }
        });
         
         
         int L =1;
         while(L < maxX) {//如果不散列化的话,可以用maxX值,前提maxX值最大值不能超多三十万
             L = L+L;
         }
         
         tree = new int[2*L];
         
         for (int j = 1; j <= N; j++) {
             int e = L+arr[j][0];//e代表x的坐标值,坐标值,第一个叶子节点值是0
            int q = query(L,e);//查询的是e位置以左包括e位置的已经处理的星星节点的个数,也代表星星级数代表q级
            count[q]++;//q级星星个数加1
            update(e,tree[e]+1);//更新e位置的树加1表示该位置又处理了一颗星
        }
         for (int j = 0; j < N; j++) {
            System.out.println(count[j]);
        }
         
     }

    private static void update(int idx, int val) {
        tree[idx]=val;
        idx=idx/2;
        while(idx>0) {
            tree[idx]=tree[idx*2]+tree[idx*2+1];
            idx=idx/2;
        }
        
    }

    private static int query(int s, int e) {
        int result=0;
        while(s<=e) {
            if(s%2==1) {
                result=tree[s]+result;
            }
            if(e%2==0) {
                result=tree[e]+result;
            }
            s=(s+1)/2;
            e=(e-1)/2;
        }
        return result;
    }
}
View Code

 

IndexTree-POJ2352_javaIndexTree-POJ2352_java_02
package Week3;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
import java.util.TreeSet;

//描述
//
//天文学家经常检查恒星地图,其中恒星以平面上的点表示,每颗恒星都有笛卡尔坐标。让恒星的水平成为不高而不是在给定恒星右边的恒星的数量。天文学家想知道恒星水平的分布。
//例如,查看上图上显示的
//地图。5号星的水平等于3(它由三颗星组成,编号为1、2和4)。以2和4为数的恒星水平为1。在这张地图上,只有0级的一颗星,1级的两颗星,2级的一颗星和3级的一颗星。
//您要编写一个程序,该程序将计算给定地图上每个级别的星星
//数量。
//
//输入
//
//输入文件的第一行包含多个星 N (1<=N<=15000)。以下 N 行描述恒星坐标(每行由 0 <+X、Y <=32000 隔开两个整数 X 和 Y)。飞机的某一点只能有一颗星星。星星按Y坐标的上升顺序排列。具有等于 Y 坐标的星星按 X 坐标的升序排列。
//输出
//
//输出应包含 N 行,每行一个数字。第一行包含 0 级的恒星量,第二行包含 1 级的恒星量等,最后一行包含 N-1 级的恒星量。
//示例输入
//
//5
//1 1
//5 1
//7 1
//3 3
//5 5
//样本输出
//
//1
//2
//1
//1
//0

//散列话做法
public class POJ2352_SanLieHua {
     static int N;
     static int tree[];//叶子节点表示当前已经处理的星星的个数,tree[1]表示当前处理星星的总的个数
     static int count[];//count[0]表示当前0级星星的个数,count[1]表示当前1级星星的个数,等等
     static TreeSet<Integer> set = new TreeSet<Integer>();
     static Map<Integer,Integer> map = new HashMap<Integer,Integer>();
     static int arr[][];
    
     public static void main(String[] args) throws Exception {
        System.setIn(new FileInputStream("Solution.txt"));
         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
         StringTokenizer st = null;
         st = new StringTokenizer(br.readLine());
         N = Integer.parseInt(st.nextToken());
         count = new int[N+1];
         arr = new int[N+1][2];
         int maxX = 0;
         for (int i = 1; i <= N; i++) {
             st = new StringTokenizer(br.readLine());
             int x = Integer.parseInt(st.nextToken());
             int y = Integer.parseInt(st.nextToken());
             arr[i][0]=x;
             arr[i][1]=y;
             maxX = Math.max(x, maxX);
         }
         Arrays.sort(arr, 1, N+1, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1]==o2[1]?o1[0]-o2[0]:o1[1]-o2[1]; //思路y坐标升序,y坐标相等时,x升序
            }
        });
         
         for (int i = 1; i <= N; i++) {
            set.add(arr[i][0]); //TreeSet去重加排序
        }
         
         //散列化
         int i=1;
         while(!set.isEmpty()) {
             map.put(set.pollFirst(), i++);
         }
         int L =1;
         while(L < N) {//散列化后set个数变小了可以用N的个数求tree的L的大小值,如果不散列化的话,可以用maxX值,前提maxX值最大值不能超多三十万
             L = L+L;
         }
         
         tree = new int[2*L];
         //1,3,5,7散列话之后是1,2,3,4
         for (int j = 1; j <= N; j++) {
             //map.get(arr[j][0]) 原数组中这个值排的位置大小,对应跟新树上的索引对应的位置
             int e = L+map.get(arr[j][0])-1;//注意:是否减一,这里减一就是包括当前位置的计数
            int q = query(L,e);//查询的是e位置以左包括当前位置已经处理的星星节点的个数,也代表星星级数代表q级
            count[q]++;//q级星星个数加1
            update(e,tree[e]+1);//更新e位置的树加1表示该位置又处理了一颗星
        }
         for (int j = 0; j < N; j++) {
            System.out.println(count[j]);
        }
         
     }

    private static void update(int idx, int val) {
        tree[idx]=val;
        idx=idx/2;
        while(idx>0) {
            tree[idx]=tree[idx*2]+tree[idx*2+1];
            idx=idx/2;
        }
        
    }

    private static int query(int s, int e) {
        int result=0;
        while(s<=e) {
            if(s%2==1) {
                result=tree[s]+result;
            }
            if(e%2==0) {
                result=tree[e]+result;
            }
            s=(s+1)/2;
            e=(e-1)/2;
        }
        return result;
    }
}
View Code