2021-01-08

85 阅读1分钟
 import java.util.Scanner;
 public class Main{
     static int N = 100010;
     static int[] q = new int[N];
     static int[] temp = new int[N];
     
     public static void merge_sort(int[] q,int l,int r){
         if(l >= r) return ;
         int mid = (l + r)/2;
         merge_sort(q,l,mid);
         merge_sort(q,mid + 1, r);
         int i = l, j = mid + 1;
         int k = 0;
         while(i <= mid && j <= r){
             if(q[i] < q[j]) temp[k++] = q[i++];
             else temp[k++] = q[j++];
         }
         while(i <= mid) temp[k++] = q[i++];
         while(j <= r) temp[k++] = q[j++];
         for(i = l,j = 0; i <= r;i++,j++)
             q[i] = temp[j];
     }
     public static void main(String[] args){
         Scanner sc = new Scanner(System.in);
         int n = sc.nextInt();
         for(int i = 0; i < n; i++) q[i] = sc.nextInt();
         merge_sort(q,0,n - 1);
         for(int i = 0; i < n; i++) System.out.printf("%d ",q[i]);
         
     }
 }

差分: 差分其实是前缀和的逆运算,我们知道假设一个数组:a[0]、a[1]、....a[n],那它们的前缀和为s[0]、s[1]、...s[n],至于怎么求,我就不细讲了。

那现在我们还是有这么一个已知的数组a[0]、a[1]、....a[n],那么我们就要构造出一个b[0]、b[1]、...b[n],它们是数组a的差分,同时数组a是数组b的前缀和。

至于为什么,首先要知道数组b是怎么算出来的

image.png

所以就是这么构造出来的,有人会觉得很神奇,但确实这么神奇,但这个差分有什么用呢,更详细的说为什么要用差分,这种一种是用来算某个区间要同时加上某个数,如果单纯用循环来加的话,时间复杂度为O(n),但如果是差分,则O(1)的复杂度就可以解决。

核心代码:

 public static void insert(int l,int r,int c){
     b[l] +=c;
     b[r + 1] -=c;
 }

为什么是这样子呢,这里我们可以验证一下,首先是b[l]+=c,这里l区间加c,然后我们知道a[n]是数组b的前n项和,从a[l]开始,它一定会包含b[l],为什么呢,我们可以看看

image.png

完整代码

 import java.util.Scanner;
 public class Main{
     static int N = 100010;
     static int[] a = new int[N];
     static int[] b = new int[N];
     public static void insert(int l,int r,int c){
         b[l] += c;
         b[r + 1] -= c;
     }
     public static void main(String[] args){
         Scanner sc = new Scanner(System.in);
         int n = sc.nextInt();
         int m = sc.nextInt();
         for(int i = 1; i <= n; i++){
             a[i] = sc.nextInt();
             //同理,我们可以将输入的数拆成差分的形式,给数组b
             insert(i,i,a[i]);
         }
         while(m -- > 0){
             int l = sc.nextInt();
             int r = sc.nextInt();
             int c = sc.nextInt();
             insert(l,r,c);
         }
         
         for(int i = 1; i <= n; i++){
             //算出前缀和,实际上就是求出数组a,只不过省略罢了
             b[i] += b[i - 1];
             System.out.printf("%d ",b[i]);
         }
     }
 }

二维差分

 import java.util.Scanner;
 public class Main{
     static int N = 1010;
     static int[][] a = new int[N][N];
     static int[][] b = new int[N][N];
     public static void insert(int x1,int y1,int x2,int y2,int c){
         b[x1][y1] +=c;
         b[x2 + 1][y1] -= c;
         b[x1][y2 + 1] -= c;
         b[x2 + 1][y2 + 1] += c;
     }
     
     public static void main(String[] args){
         Scanner sc = new Scanner(System.in);
         int n = sc.nextInt();
         int m = sc.nextInt();
         int q = sc.nextInt();
         for(int i = 1; i  <= n; i++){
             for(int j = 1; j <= m; j++){
                 a[i][j] = sc.nextInt();
                 insert(i,j,i,j,a[i][j]);
             }
         }
         
         while(q-- > 0){
             int x1 = sc.nextInt();
             int y1 = sc.nextInt();
             int x2 = sc.nextInt();
             int y2 = sc.nextInt();
             int c = sc.nextInt();
             insert(x1,y1,x2,y2,c);
         }
         for(int i = 1; i <= n;i++){
             for(int j = 1; j <= m;j++){
                 b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
                 System.out.printf("%d ",b[i][j]);
             }
             System.out.println();
         }
         
     }
 }
 import java.io.*;
 public class Main{
     static int N = 1010;
     static int[][] a = new int[N][N];
     static int[][] b = new int[N][N];
     static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
     public static void insert(int x1,int y1,int x2,int y2,int c){
         b[x1][y1] += c;
         b[x1][y2 + 1] -= c;
         b[x2 + 1][y1] -= c;
         b[x2 + 1][y2 + 1] += c;
     }
     public static void main(String[] args) throws IOException{
         String[] str = br.readLine().split(" ");
         int n = Integer.parseInt(str[0]);
         int m = Integer.parseInt(str[1]);
         int q = Integer.parseInt(str[2]);
         for(int i = 1; i <= n; i++){
             str = br.readLine().split(" ");
             for(int j = 1; j <= m; j++){
                 a[i][j] = Integer.parseInt(str[j - 1]);
                 insert(i,j,i,j,a[i][j]);
             }
         }
         while(q -- > 0){
             str = br.readLine().split(" ");
             int x1 = Integer.parseInt(str[0]);
             int y1 = Integer.parseInt(str[1]);
             int x2 = Integer.parseInt(str[2]);
             int y2 = Integer.parseInt(str[3]);
             int c  = Integer.parseInt(str[4]);
             insert(x1,y1,x2,y2,c);
         }
         for(int i = 1; i <= n; i++){
             for(int j = 1; j <= m ;j ++){
                 b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
                 bw.write(b[i][j] + " ");
             }
             bw.write("\n");
         }
         
         br.close();
         bw.flush();
         bw.close();
         
     }
 }

\