Algorithm self-study __ monotonic queue

References:

Algorithm Introduction

Monotonic queue can be done in O ( n ) O(n)In the time complexity of O ( n ) , find the length of nnIn a sequence of n , each length ismmThe maximum value of the interval of m .

algorithm thinking

Visual understanding: In each cycle, first check whether the "senior" at the head of the team has graduated , then kick out all the seniors who are inferior to the "freshmen" in the queue, and finally let the freshmen join the team.

The specific algorithm idea can be found in reference materials.

Example 1 P2216 [HAOI2007] ideal square

topic description

There is a × ba \times ba×A matrix composed of integers of b , now please find an × nn \times nn×A square region of n such that the difference between the maximum and minimum values ​​of all numbers in the region is minimized.

input format

First line 3 33 integers, respectively representinga, b, na, b, na,b,The value of n .

The second row to the first a + 1 a+1a+1 line for each linebbb non-negative integers, representing the number at the corresponding position in the matrix. Each row is separated by a space between two adjacent numbers.

output format

Only one integer, for a × ba \times ba×All n × nn \times nin the b matrixn×The minimum value of the difference between the largest integer and the smallest integer in an n square area".

Example #1

Sample Input #1

5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2

Sample output #1

1

hint

All numbers in the matrix do not exceed 1 , 000 , 000 , 000 1,000,000,0001,000,000,000

100 % 100\% 100% confidence2≤ a , b ≤ 1000 , n ≤ a , n ≤ b , n ≤ 100 2 \and a,b \and 1000,n \and a,n \and b,n \and2a,b1000,na,nb,n100

train of thought

General idea: use a monotone queue to find each n × nn\times nn×The maximum and minimum values ​​of n squares, and then traverse each square to update the answer.

Take finding the maximum value within a square as an example. First scan each row of the input matrix, and find the length of each row is nnThe maximum value of the interval of nmmax[][] , stored in the matrix . Then scanmmax[][]each legal column in and find each lengthnnThe maximum value of the interval of nmmmax[][] , stored in the matrix .

the code

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e3+5;

int a, b, n;
int mtx[maxn][maxn];
int mmax[maxn][maxn];
int mmmax[maxn][maxn];
int mmin[maxn][maxn];
int mmmin[maxn][maxn];
int ans = 0x7fffffff; 

int main(){
    
    
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin>>a>>b>>n;
	for(int i=1;i<=a;i++){
    
    
		for(int j=1;j<=b;j++){
    
    
			cin>>mtx[i][j];
		}
	}
	// 求正方形内最大值
	for(int i=1;i<=a;i++){
    
    
		deque<int> q;
		for(int j=1;j<=b;j++){
    
    
			if(!q.empty() && j-q.front()+1>n) q.pop_front();
			while(!q.empty() && mtx[i][j]>mtx[i][q.back()]) q.pop_back();
			q.push_back(j);
			if(j>=n){
    
    
				mmax[i][j] = mtx[i][q.front()];
			}
		}
	} 
	for(int j=n;j<=b;j++){
    
    
		deque<int> q;
		for(int i=1;i<=a;i++){
    
    
			if(!q.empty() && i-q.front()+1>n) q.pop_front();
			while(!q.empty() && mmax[i][j]>mmax[q.back()][j]) q.pop_back();
			q.push_back(i);
			if(i>=n){
    
    
				mmmax[i][j] = mmax[q.front()][j];
			}
		}
	}
	// 求正方形内最小值 
	for(int i=1;i<=a;i++){
    
    
		deque<int> q;
		for(int j=1;j<=b;j++){
    
    
			if(!q.empty() && j-q.front()+1>n) q.pop_front();
			while(!q.empty() && mtx[i][j]<mtx[i][q.back()]) q.pop_back();
			q.push_back(j);
			if(j>=n){
    
    
				mmin[i][j] = mtx[i][q.front()];
			}
		}
	} 
	for(int j=n;j<=b;j++){
    
    
		deque<int> q;
		for(int i=1;i<=a;i++){
    
    
			if(!q.empty() && i-q.front()+1>n) q.pop_front();
			while(!q.empty() && mmin[i][j]<mmin[q.back()][j]) q.pop_back();
			q.push_back(i);
			if(i>=n){
    
    
				mmmin[i][j] = mmin[q.front()][j];
			}
		}
	}
	// 求最终答案 
	for(int i=n;i<=a;i++){
    
    
		for(int j=n;j<=b;j++){
    
    
			ans = min(ans, mmmax[i][j]-mmmin[i][j]);
		}
	}
	cout<<ans; 
	return 0;
}

Example 2 P2034 select number

topic description

Given a row of nnn non-negative integersa 1 ⋯ an a_1 \cdots a_na1an. Now you can choose some of them, but there cannot be more than kkk consecutive numbers are selected. Your task is to maximize the sum of the selected numbers.

input format

The first line of two integers nnn k k k

following nnn lines, one integer per line representsai a_iai

output format

Output a value representing the answer.

Example #1

Sample Input #1

5 2
1
2
3
4
5

Sample output #1

12

hint

For 100 % 100\%100% of the data,1 ≤ n ≤ 100000 1 \le n \le 1000001n100000,1 ≤ k≤ n 1 \le k \le n1kn0 ≤ 0 \le0 number size≤ 1 , 000 , 000 , 000 \le 1,000,000,0001,000,000,000

train of thought

This question is a classic example of dynamic programming for monotonic queue optimization .

Convert the topic to: delete several numbers from the topic, and the difference between the serial numbers of any two deleted numbers is less than or equal to k. Under the premise of meeting the requirements of the topic, the sum of the deleted numbers should be as small as possible.

Defining the state dp[i]means: Considering only the first inumber and deleting the first inumber, the smallest sum to be deleted. The state transition equation is:
dp [ i ] = { a [ i ] , i ≤ k + 1 a [ i ] + min ⁡ i − k − 1 ≤ j ≤ i − 1 dp [ j ] , i > k + 1 dp [i] = \begin{cases} a[i],\ i\leq k+1\\ a[i]+\min\limits_{ik-1 \leq j\leq i-1} dp[j], \i>k+1 \end{cases}dp[i]= a[i], ik+1a[i]+ik1ji1mindp[j], i>k+1

It can be seen that the state transition needs to use the maximum value of the fixed-length interval , so monotonic queue optimization can be used.

the code

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int maxn = 1e5+5; 

int n, k;
int a[maxn];
int dp[maxn];
int sum = 0;
int ans = 0x7fffffff;
deque<int> q;

signed main(){
    
    
	cin>>n>>k;
	k += 1;
	for(int i=1;i<=n;i++){
    
    
		cin>>a[i];
		sum += a[i];
	}
	for(int i=1;i<=n;i++){
    
    
		if(!q.empty() && i>k) dp[i] += dp[q.front()];
		dp[i] += a[i];
		if(!q.empty() && i-q.front()+1>k) q.pop_front();
		while(!q.empty() && dp[i]<dp[q.back()]) q.pop_back();
		q.push_back(i);
	}
	ans = sum;
	for(int i=n-k+1;i<=n;i++){
    
    
		ans = min(ans, dp[i]);
	}
	cout<<sum-ans;
	return 0;
}

Example 3 P2698 [USACO12MAR] Flowerpot S

topic description

The boss needs your help watering the flowers. gives NNCoordinates of N drops of water, yyy represents the height of the droplet,xxx means it falls toxxThe position of the x- axis.

1 per second per dropFalling at a speed of 1 unit length. You need to place the flower pot atxxA certain position on the x- axis makes the 1st11 drop of water starts, to the last1 11 drop ends with a time difference of at leastDDD

We believe that as long as the water drop reaches xxOn the x- axis, it is considered to be caught if it is aligned with the edge of the flowerpot. givesNNCoordinates of N drops andDDFor the size of D , please calculate the width WWof the smallest flower potW

input format

first line 2 22 integersNNN andDDD

Next NNN lines each line2 22 integers, representing the coordinates of the water drop( x , y ) (x,y)(x,y)

output format

Only one row 1 11 integer, indicating the width of the smallest flowerpot. If it is not possible to construct a pot wide enough thatthe DDD units of time to catch the water droplets that meet the requirements, then output− 1 -11

Example #1

Sample Input #1

4 5
6 3
2 4
4 10
12 15

Sample output #1

2

hint

100 % 100\% 100% of data:1 ≤ N ≤ 1 0 5 1 \le N \le 10 ^ 51N1051 ≤ D ≤ 1 0 6 1 \le D \le 10 ^ 61D1060 ≤ x , y ≤ 1 0 6 0\le x,y\le10^60x,y106

train of thought

Binary answer + monotonic queue

It should be noted that the condition for the head of the team to leave the team is: the xx of the current water drop and the water drop at the head of the teamThe difference in x coordinatesis greater than the pot width.

the code

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;

struct NODE{
    
    
	int x, y;
	bool operator<(const NODE& a)const{
    
    
		if(x==a.x) return y<a.y;
		else return x<a.x;
	}
};

NODE node[maxn];
int n, d;
int m = 0x7fffffff, M = -1;
int L = 0x7fffffff, R = -1;
int ans = 0x7fffffff;

bool check(int len){
    
    
	deque<int> q1, q2;
	for(int i=1;i<=n;i++){
    
    
		if(!q1.empty() && node[i].x-node[q1.front()].x>len) q1.pop_front();
		if(!q2.empty() && node[i].x-node[q2.front()].x>len) q2.pop_front();
		while(!q1.empty() && node[i].y>node[q1.back()].y) q1.pop_back();
		while(!q2.empty() && node[i].y<node[q2.back()].y) q2.pop_back();
		q1.push_back(i);
		q2.push_back(i);
		if(node[q1.front()].y-node[q2.front()].y >= d) return true;
	}
	return false;
}

int main(){
    
    
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin>>n>>d;
	for(int i=1;i<=n;i++){
    
    
		cin>>node[i].x>>node[i].y;
		m = min(m, node[i].y);
		M = max(M, node[i].y);
		L = min(L, node[i].x);
		R = max(R, node[i].x);
	} 
	sort(node+1, node+1+n);
	R = R-L, L = 0;
	if(M-m<d){
    
    
		cout<<-1;
		return 0;
	}
	while(L <= R){
    
    
		int mid = (L+R)>>1;
		if(check(mid)){
    
    
			ans = min(ans, mid);
			R = mid-1;
		}
		else{
    
    
			L = mid+1;
		}
	}
	cout<<ans;
	return 0;
}

Guess you like

Origin blog.csdn.net/MaTF_/article/details/129314251