表格计算

某次无聊中, atm 发现了一个很老的程序。这个程序的功能类似于 Excel ,它对一个表格进行操作。
不妨设表格有 n 行,每行有 m 个格子。
每个格子的内容可以是一个正整数,也可以是一个公式。
公式包括三种:

  1. SUM(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的和。
  2. AVG(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的平均数。
  3. STD(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的标准差。

标准差即为方差的平方根。
方差就是:每个数据与平均值的差的平方的平均值,用来衡量单个数据离开平均数的程度。

公式都不会出现嵌套。

如果这个格子内是一个数,则这个格子的值等于这个数,否则这个格子的值等于格子公式求值结果。

输入这个表格后,程序会输出每个格子的值。atm 觉得这个程序很好玩,他也想实现一下这个程序。

「输入格式」
第一行两个数 n, m 。
接下来 n 行输入一个表格。每行 m 个由空格隔开的字符串,分别表示对应格子的内容。
输入保证不会出现循环依赖的情况,即不会出现两个格子 a 和 b 使得 a 的值依赖 b 的值且 b 的值依赖 a 的值。

「输出格式」
输出一个表格,共 n 行,每行 m 个保留两位小数的实数。
数据保证不会有格子的值超过 1e6 。

「样例输入」
3 2
1 SUM(2,1:3,1)
2 AVG(1,1:1,2)
SUM(1,1:2,1) STD(1,1:2,2)

「样例输出」
1.00 5.00
2.00 3.00
3.00 1.48

「数据范围」
对于 30% 的数据,满足: n, m <= 5
对于 100% 的数据,满足: n, m <= 50

资源约定:
峰值内存消耗(含虚拟机) < 512M
CPU消耗 < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static int n, m;
    public static double[][] value;
    
    public double getSum(int x1, int y1, int x2, int y2) {
        double sum = 0;
        for(int i = x1;i <= x2;i++)
            for(int j = y1;j <= y2;j++)
                sum = sum + value[i][j];
        return sum;
    }
    
    public double getAvg(int x1, int y1, int x2, int y2) {
        int count = Math.abs((x2 - x1 + 1) * (y2 - y1 + 1));
        double avg = getSum(x1, y1, x2, y2) / count;
        return avg;
    }
    
    public double getStd(int x1, int y1, int x2, int y2) {
        int count = Math.abs((x2 - x1 + 1) * (y2 - y1 + 1));
        double avg = getAvg(x1, y1, x2, y2);
        double result = 0;
        for(int i = x1;i <= x2;i++)
            for(int j = y1;j <= y2;j++)
                result = result + (value[i][j]-avg) * (value[i][j]-avg);
        result = Math.sqrt(result / count);
        return result;
    }
    
    public boolean check(int x1, int y1, int x2, int y2) {
        boolean judge = true;
        for(int i = x1;i <= x2;i++) {
            if(!judge)
                break;
            for(int j = y2;j <= y2;j++) {
                if(value[i][j] == -1) {
                    judge = false;
                    break;
                }
            }
        }
        return judge;
    }
    
    public String[] getOperaAndNum(String arrayA) {
        int p = arrayA.indexOf("(");
        int q = arrayA.indexOf(")");
        String opera = arrayA.substring(0, p);
        arrayA = arrayA.replace(':', ',');
        String[] num = arrayA.substring(p+1, q).split(",");
        String[] result = new String[5];
        result[0] = opera;
        for(int i = 0;i < 4;i++)
            result[i + 1] = num[i];
        return result;
    }
    
    public void getResult(String[] A) {
        value = new double[n][m];
        ArrayList<String> list = new ArrayList<String>();
        for(int i = 0;i < n;i++)
            for(int j = 0;j < m;j++) 
                value[i][j] = -1;
        for(int i = 0;i < A.length;i++) {
            String[] arrayA = A[i].split(" ");
            for(int j = 0;j < arrayA.length;j++) {
                if(arrayA[j].charAt(0) >= '0' && arrayA[j].charAt(0) <= '9') {
                    value[i][j] = Double.valueOf(arrayA[j]);
                } else {
                    String[] r = getOperaAndNum(arrayA[j]);
                    String opera = r[0];
                    int x1 = Integer.valueOf(r[1]) - 1;
                    int y1 = Integer.valueOf(r[2]) - 1;
                    int x2 = Integer.valueOf(r[3]) - 1;
                    int y2 = Integer.valueOf(r[4]) - 1;
                    if(check(x1, y1, x2, y2) == false) {
                        list.add(""+i+" "+j+" "+arrayA[j]);
                        continue;
                    }
                    if(opera.equals("SUM"))
                        value[i][j] = getSum(x1, y1, x2, y2);
                    else if(opera.equals("AVG"))
                        value[i][j] = getAvg(x1, y1, x2, y2);
                    else if(opera.equals("STD"))
                        value[i][j] = getStd(x1, y1, x2, y2);
                }
            }
        }
    
        while(!list.isEmpty()) {
            for(int i = list.size() - 1;i >= 0;i--) {
                String[] temp = list.get(i).split(" ");
                int a = Integer.valueOf(temp[0]);
                int b = Integer.valueOf(temp[1]);
                String[] r = getOperaAndNum(temp[2]);
                String opera = r[0];
                int x1 = Integer.valueOf(r[1]) - 1;
                int y1 = Integer.valueOf(r[2]) - 1;
                int x2 = Integer.valueOf(r[3]) - 1;
                int y2 = Integer.valueOf(r[4]) - 1;
                if(check(x1, y1, x2, y2) == false) 
                    continue;
                if(opera.equals("SUM"))
                    value[a][b] = getSum(x1, y1, x2, y2);
                else if(opera.equals("AVG"))
                    value[a][b] = getAvg(x1, y1, x2, y2);
                else if(opera.equals("STD"))
                    value[a][b] = getStd(x1, y1, x2, y2);
                list.remove(i);
            }
        }
        for(int i = 0;i < n;i++) {
            for(int j = 0;j < m;j++) {
                System.out.printf("%.2f", value[i][j]);
                if(j != m - 1)
                    System.out.print(" ");
            }
            System.out.println();
        }
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        m = in.nextInt();
        in.nextLine();
        String[] A = new String[n];
        for(int i = 0;i < n;i++)
            A[i] = in.nextLine();
        test.getResult(A);
    }
}