Algorithm Advanced Guide-Basic Algorithm-Prefix Sum and Difference

1. Laser bomb
problem link
Insert picture description here
solution: The solution of this problem is a bit similar to prefix and sum. If this problem is to give you a line segment, each point on the line segment has its corresponding value. There is a bomb that can destroy a line segment of length n. The maximum total value that can be destroyed, then it is easy to solve by prefix sum, and this problem is to turn the one-dimensional prefix sum into a two-dimensional prefix sum. The explosion range of the bomb is a square, we only need to know the diagonal The position of the last two points can determine the triangle, so we use a two-dimensional array f[x][y] to represent the value of the 0 0 point and the rectangle determined by the x and y points. Then this question is also Converted into a prefix and question. The question now is how to deal with this two-dimensional array.
Look at the following code (f[i][j] stores the value of the point before processing)

for(int i = 1; i <= 5001; ++ i)
        {
    
    
            for(int j = 1; j <= 5001; ++ j)
            {
    
    
                f[i][j] = f[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1];
            }
        }

Then this question will be easily solved

c++ code:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 5000 + 50;
typedef long long ll;
int f[maxn][maxn];
int main()
{
    
    
    int n, r;
    while(scanf("%d%d", &n, &r) != EOF)
    {
    
    
        if(r == 0)
        {
    
    
            printf("0\n");
            continue;
        }
        int x, y, v;
        memset(f, 0, sizeof(f));
        for(int i = 0; i < n; ++ i)
        {
    
    
            scanf("%d%d%d", &x, &y, &v);
            f[x+1][y+1] = v;
        }
        for(int i = 1; i <= 5001; ++ i)
        {
    
    
            for(int j = 1; j <= 5001; ++ j)
            {
    
    
                f[i][j] = f[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1];
            }
        }
        int ans = 0;
        for(int i = r; i <= 5001; ++ i)
        {
    
    
            for(int j = r; j <= 5001; ++ j)
            {
    
    
                ans = max(ans, f[i][j]-f[i-r][j]-f[i][j-r]+f[i-r][j-r]);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

java code:

import java.util.Scanner;

public class Main
{
    
    
	static final int N=5001;
	static int[][] s=new int[N+5][N+5];
	public static void main(String[] args) {
    
    
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int r=sc.nextInt();
		for(int i=0;i<n;i++)
		{
    
    
			int x=sc.nextInt();
			int y=sc.nextInt();
			int v=sc.nextInt();
			s[x+1][y+1]=v;
		}
		for(int i=1;i<=N;i++)
		{
    
    
			for(int j=1;j<=N;j++)
			{
    
    
				s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+s[i][j];
			}
		}
		int _max=0;
		for(int i=r;i<=N;i++)
		{
    
    
			for(int j=r;j<=N;j++)
			{
    
    
				if(s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r]>_max)
					_max=s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r];
			}
		}
		System.out.println(_max);
		sc.close();
	}
}


2.
Link to IncDec Sequence
Insert picture description here
Question Solution: First of all, one of the key points of this question is the modification operation of the interval [l, r]. Because the modification operation of this topic has a feature, that is, it only adds one or only subtracts one, instead of +x or −x, so we don’t need to use advanced data structures, line segment trees and tree arrays. But just need to use difference.
How to ensure that each number is the same, only need to ensure that the difference between adjacent 2 numbers is 0. Suppose we store the difference of all adjacent 2 numbers in the array b[n], b[n]=a[ n]-a[n-1]; So at this time we are trying to find a way to turn the array of b[n] into 0. Let’s look at the effect of adding one or subtracting a pair of b[n] to an interval in the title. Let [ Add one to the number of the a, b] segment, and then add one to b[b] minus one b[a]. In order to make the b array become 0 as soon as possible, through the greedy idea, we make the positive and negative pairs of the b array, and the positive number minus one negative number is added One, if there are many positive or negative numbers, let it and b[1], because whether b[1] is 0 does not affect the
C++ code:

#include <bits/stdc++.h>

using namespace std;

int main() {
    
    
  vector<int> d;
  d.push_back(0);
  int n, x, y;
  cin >> n;
  cin >> x;
  for (int i = 1; i < n; i++) {
    
    
    cin >> y;
    d.push_back(y - x);
    x = y;
  }
  long long pos = 0, neg = 0;
  for (auto x : d) {
    
    
    if (x > 0) pos += x;
    else neg -= x;
  }
  cout << min(pos, neg) + abs(pos - neg) << endl;
  cout << abs(pos - neg) + 1;
  return 0;
}

java code:

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

public class Main {
    
    
    static final int N=100000+10;
    public static void main(String[] args) {
    
    
        Scanner sc=new Scanner(System.in);
        int n;
        long a[]=new long [N];
        n= sc.nextInt();
        for(int i=1;i<=n;i++)
            a[i]=sc.nextInt();
        long q,p;
        q=0;
        p=0;
        for(int i=n;i>=2;i--)
        {
    
    
            long x=a[i]-a[i-1];
            if(x>0)
                q+=x;
            else
                p-=x;

        }
        System.out.println(Math.max(q,p));
        System.out.println(Math.abs(q-p)+1);


    }




}

3.Tallest cow
problem link
Insert picture description here
solution: In order to make each cow the highest height, the first cow and the last cow can have the highest height given by the problem, and then the rest of the cows can be obtained according to the difference relationship. Assuming that a and b can see each other, it means that the cow between a and b is shorter than ab, then cha[a+1]-1 cha[b]+1;
c++ code:

#include <iostream>
#include <cstdio>
#include <cmath>
 
using namespace std;
 
int N, P, H, M;
int a[10005];
bool appear[10005][10005];
 
int main()
{
    
    
    cin >> N >> P >> H >> M;
    a[1] = H;
    for (int i = 1, A, B; i <= M; i ++ )
    {
    
    
        cin >> A >> B;
        if(A > B) swap(A, B);
        if(!appear[A][B])
        {
    
    
            appear[A][B] = 1;
            a[A + 1] --, a[B] ++;
        }
    }
 
    for (int i = 1; i <= N; i ++ )
        a[i] += a[i - 1], cout << a[i] << endl;
    return 0;
}


java code:

import java.util.*;
public class Main {
    
    

    public static void main(String[] args) {
    
    
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] arr = new int[n + 1];
        int p = cin.nextInt();
        int h = cin.nextInt();
        Arrays.fill(arr, h);
        int m = cin.nextInt();
        Set<String> set = new HashSet<String>();
        int[] op = new int[2];
        for (int i = 0; i < m; i++) {
    
    
            op[0] = cin.nextInt(); // A
            op[1] = cin.nextInt(); // B
            Arrays.sort(op);
            if (!set.contains(op[0] + "" + op[1])) {
    
    
                set.add(op[0] + "" + op[1]);
                for (int c = op[0] + 1; c < op[1]; c++)
                    arr[c]--;
            }
        }
        for (int i = 1; i <= n; i++)
            System.out.println(arr[i]);
    }
}


Guess you like

Origin blog.csdn.net/jahup/article/details/108361206