백준공부/java

[백준] 25711번 인경산 (gold 5

gomduri43 2023. 6. 23. 16:48

import java.io.*;
import java.util.*;

class Point{
    double x;
    double y;
    double value;
    double reverseValue;
    public Point(double x, double y, double value,double reverseValue ){
        this.x=x;
        this.y=y;
        this.value=value;
        this.reverseValue=reverseValue;
    }
}
public class Main{
    public static void main(String[]args) throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st=new StringTokenizer(br.readLine());
        int div=1000000;
        int n=Integer.parseInt(st.nextToken());
        int q=Integer.parseInt(st.nextToken());
        st=new StringTokenizer(br.readLine());
        StringTokenizer st2=new StringTokenizer(br.readLine());
        Point[] map=new Point[n+1];
        map[0]=new Point(0l,0l,0,0);
        map[1]=new Point(Double.parseDouble(st.nextToken())/div,Double.parseDouble(st2.nextToken())/div,0,0);
        for(int i=2; i<=n; i++){
            double x=Double.parseDouble(st.nextToken())/div;
            double y=Double.parseDouble(st2.nextToken())/div;
            double distance=Math.sqrt(Math.pow(x-map[i-1].x,2)+ Math.pow(y-map[i-1].y,2));
            double reverseValue;
            if(y>map[i-1].y){
                reverseValue=distance;
                distance*=3;
            }
            else if(y==map[i-1].y){
                distance*=2;
                reverseValue=distance;
            }
            else{
                reverseValue=distance*3;
            }

            map[i]=new Point(x,y,distance+map[i-1].value,reverseValue+map[i-1].reverseValue);
        }

        for(int i=0; i<q; i++) {
            st = new StringTokenizer(br.readLine());
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            if (start < end) {
                bw.write((map[end].value - map[start].value)*div + "\n");
            }
            else{
                bw.write((map[start].reverseValue - map[end].reverseValue)*div + "\n");
            }
        }
        bw.flush();
    }

}


//이문제에서 가장 오랜 시간이 걸린 부분은 소수점 표현이었다. 소수점 표현을 잘 안해본것도 있었고
//계속 예제2 케이스에서 소수점이 4.xxxxxxxxxx e9 와 같이 표현되었따.
//결론을 말하면, 위와같은 표현도 결국에 함축적으로 4.xxxxxx 10e9승으로 결국은
//똑같은 수를 나타내기에 정답처리가 되었다.

//여기서 크게 두가지를 깨달았는데 위처럼 똑같은 표현이라는 것
//만약 좀더 정밀하게 하고자하면, 위방법처럼 x,y에 일정수를 나누고 추후에 곱하여 설정하는것

//여기서 그냥 long으로 계산하면 10의 9승은 10의 18승이 되었다가, sqrt에서 다시 10의 9승이된다.
//이때 double은 모든 수 표현이가능하므로, 딱히 그수가 int 범위를 초과해도 상관없다. 단
//소수의 정밀도는 떨어지지만 말이다.
//문제에서 주어진대로 출력하면 되므로, string.format이나 System.out.printf("%.12f",(double 자료형));
//으로 출력하면됨
import java.io.*;
import java.util.*;

class Point{
    double x;
    double y;
    public Point(double x, double y){
        this.x=x;
        this.y=y;
    }
}
public class Main{
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.valueOf(st.nextToken());
        int q=Integer.valueOf(st.nextToken());

        st=new StringTokenizer(br.readLine());
        StringTokenizer st2=new StringTokenizer(br.readLine());

        Point[] home=new Point[n+1];
        for(int i=1; i<=n; i++){
            home[i]=new Point(Double.valueOf(st.nextToken()) , Double.valueOf(st2.nextToken()));
        }

        double[] fd=new double[n+1]; //정방향
        double[] bd=new double[n+1]; //역방향

        for(int i=1; i<n; i++){
            int mul=com(home[i], home[i+1]);
            fd[i+1]=fd[i]+mul*Math.sqrt(Math.pow(home[i].x-home[i+1].x ,2 ) + Math.pow(home[i].y-home[i+1].y ,2));

        }

        for(int i=n; i>1; i--){
            int mul=com(home[i], home[i-1]);
            bd[i-1]=bd[i]+mul*Math.sqrt(Math.pow(home[i].x-home[i-1].x ,2 ) + Math.pow(home[i].y-home[i-1].y ,2));
        }

        for(int i=0; i<q; i++){
            st=new StringTokenizer(br.readLine());
            int s=Integer.valueOf(st.nextToken());
            int e=Integer.valueOf(st.nextToken());

            if(s==e){
                bw.write(0+"\n");
            }
            else if(s<e){
                bw.write((fd[e]-fd[s])+"\n");
            }
            else{
                bw.write((bd[e]-bd[s])+"\n");
            }
        }
        bw.flush();
    }
    public static int com(Point o1, Point o2){
        if(o1.y>o2.y){
            return 1;
        }
        else if(o2.y==o1.y){
            return 2;
        }
        else{
            return 3;
        }
    }

}


//2024 02 14에 작성한 코드. 실제로 long범위 초과 걱정안해도 double형에서 처리가 되어서 아무문제없음
//문제는 단순히 누적합+방법론에 gold5를 부여한 느낌.
//실수표현은 문제될 것이 없다.