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