[NOIP2012 Improvement Group] Borrow classroom

[NOIP2012 Improvement Group] Borrow classroom

Title description:

During college, there is often a need to rent classrooms. It is necessary to apply to the school to borrow a classroom for activities as large as the department or department, or as small as the self-study discussion in the study group. The size and function of the classrooms are different, the identities of the borrowers are different, and the procedures for borrowing the classrooms are also different.

Faced with the massive amount of information about renting classrooms, we naturally hope that programming can solve this problem.

We need to process the borrowed classroom information for the next n days, where the school has ri classrooms available for rent on the i-th day. There are m orders in total, and each order is described by three positive integers, namely dj​, sj​, tj​, indicating that a renter needs to rent a classroom from day sj​ to day tj​ (including days sj​ and On the tjth day), dj classrooms need to be rented every day.

We assume that the renter has no requirements on the size and location of the classroom. That is to say, for each order, we only need to provide dj classrooms every day, and it is not necessary to consider which classrooms they are, and whether they are the same classrooms every day.

The principle of borrowing classrooms is first-come-first-served, that is to say, we have to assign classrooms to each order in order of order. If an order cannot be fully satisfied during the assignment process, the assignment of the classroom needs to be stopped and the current applicant should be notified to revise the order. Unsatisfactory here means that from the sjth day to the tjth day, there is at least one day when the number of remaining classrooms is less than dj​.

Now we need to know if there will be orders that cannot be fully filled. If so, which applicant needs to be notified to modify the order.

input format

The first line contains two positive integers n,m, representing the number of days and the quantity of the order.

The second line contains n positive integers, where the i-th number is ri​, indicating the number of classrooms available for rent on the i-th day.

Next there are m lines, each line contains three positive integers dj​, sj​, tj​, indicating the number of leases, and the days when the lease starts and ends.

Two adjacent numbers in each line are separated by a space. Days and orders are numbered with integers starting from 1.

output format

If all orders can be satisfied, the output is just one line, containing an integer 0. Otherwise (the order cannot be fully fulfilled)

Output two lines, the first line outputs a negative integer -1, and the second line outputs the applicant number that needs to modify the order.

Input and output samples

Input #1:

4 3 
2 5 4 3 
2 1 3 
3 2 4 
4 2 4

Output #1:

-1 
2

Instructions/Tips

【Input and output sample description】

After the first order is fulfilled, the number of remaining classrooms in 4 days are 0, 3, 2, 3 respectively. The 2nd order requires 3 classrooms per day from the 2nd to the 4th day, and the remaining number of classrooms on the 3rd day is 2, so it cannot be satisfied. Allocation is stopped and the 2nd applicant is notified to modify the order.

【data range】

For 10% of the data, there are 1≤ n, m≤ 10;

For 30% of the data, there are 1≤n, m≤1000;

For 70% of the data, there are 1 ≤ n,m ≤ 10^5;

For 100% of the data, there are 1≤n, m≤10^6, 0≤ri​, dj​≤10^9, 1≤sj​≤tj​≤n.

NOIP 2012 Improvement group second day second question

2022.2.20 Add a new set of hack data

Ideas:

  1. Brief description of violence

First of all, it is not difficult for us to see that this question is not a difficult question, because obviously, when looking at the question at first glance, it is easy to think of how to fight violence: enumerate each order, and then for each Such an order, modify (subtract) each day in the interval until a certain order makes the number of classrooms left on a certain day negative, and the result can be obtained.

Let’s make a small comment first: Any violent question that can be solved almost correctly is not a difficult problem! (Konjac can fool 50+, isn’t it a water question qwq) However, obviously the violence in the form of enumeration will be very slow, and the expected time complexity is about

                                                                  O(N * M)

Might be faster ( but no use qwq )


2. Thoughts in detail

  Let's use our brains to think about it: each order can actually be regarded as an interval (operation), and the left and right intervals are the start time and end time respectively, so isn't this just an interval operation - the line segment tree is preferred! But the author does not intend to introduce the line segment tree here, because although the line segment tree is easy to operate and has low complexity, the code is too long qwq! (escape

  And I always feel that when you take a test, you can use a line segment tree template to play two more violence qwq ( although violence is not necessarily right )

  Therefore, choose to introduce a well-understood and easy-to-implement algorithm: difference array

  Before introducing the difference, you need to introduce the prefix and the idea

(qwq will only talk about one-dimensional linear prefix sums here, of course)

  **We have a set of numbers (the number is less than or equal to 10 million), and there are a lot of inquiries - given the interval l, r, find the sum of all numbers between l and r (the number of inquiries is less than or equal to 10 million) **

  Violence will definitely not work here (O(N Q length)), so let’s observe how the prefix sum is done: use sum[i] to store the sum of the first i numbers, and then use sum[r]-sum[l -1] to represent the sum of all numbers between l~r. (The reason for l-1 is that l~r only needs to contain l) and the sum array can be obtained by simple recursion

Code core:

for(int i=1;i<=n;i++){
    cin>>a[i];
    sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=q;i++){
    cin>>l>>r;
    cout<<sum[r]-sum[l-1]<<" ";
}

The so-called differential array is the inverse operation of the prefix sum array:

We give the difference between two adjacent numbers of the first i number (1<=i<=n), and find each item a[i] (1<=i<=n).

At this time, it is nothing more than obtaining each item by means of difference. At this time, we can have a difference array diff, diff[i] is used to record a[i]-a[i-1], and then for each item a[i], we can recursively come out:

for(int i=1;i<=n;i++){
    cin>>diff[i];
    a[i]=diff[i]+a[i-1];
}
for(int i=1;i<=n;i++)
  cout<<a[i]<<' ';

So far, we can see that the prefix sum is to use metadata to find the union relationship between elements, and the difference is to find metadata based on the logical relationship between elements, which is a reciprocal idea (qwq but sometimes Metadata and relational data are not easy to distinguish or produce role inversion)

However, understanding the prefix and & difference does not mean that you can definitely do the template question: after all, thinking can only be an auxiliary tool


3. About the two-point answer

  Generally speaking, dichotomy is a very useful optimization method, because it will directly lead to halving operations, and there is a defining standard for whether dichotomy can be achieved: whether the decision-making process or sequence of the state satisfies monotonicity or can be partially discarded.  In this question, because if the previous order is not satisfied, then all subsequent orders do not need to continue to be considered; and if the latter order is satisfied, then all previous orders must be satisfied, which is in line with partial abandonment. So the order quantity can be divided into two. 

4. Correct!

First of all, it is necessary to understand why interval difference is used instead of interval prefix sum: because the object of each operation of this question is the metadata given in the original question, rather than asking for a certain relationship, so difference is used.

Secondly, we need to know what role the difference will play: because the diff array determines the change size and trend of each metadata, so when we want to operate on intervals, money can be converted into an operation on the diff array:

diff[l[i]]+=d[i];
diff[r[i]+1]-=d[i];//d[i]是指每天要借的教室数

Because the following metadata are all derived from the previous diff array, changing diff[i] is equivalent to changing each value after i , and subtracting the changed amount again to achieve the purpose of operating the interval.

Then, we need to understand the strategy: start enumerating from the first order until it cannot be satisfied or the enumeration is complete.

Finally, a little reminder, my following scale is to judge whether it is satisfied by comparing the size, rather than making a difference to judge the negative number-if there is no negative number, don’t get a negative number.

Full code:
 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1000011;
ll r[N],sum[N],ID=0,d[N],s[N],t[N],a[N];
ll n,m;
bool pd(ll mid){
	memset(sum,0,sizeof(sum));
	for(ll i=1;i<=mid;i++){
		sum[s[i]]+=d[i];
		sum[t[i]+1]-=d[i];
	}
	for(ll i=1;i<=n;i++){
		a[i]=a[i-1]+sum[i];
		if(a[i]>r[i])
		  return false;
	}
	return true;
}
int main(){
	scanf("%d%d",&n,&m);
	bool f=true;
	for(ll i=1;i<=n;i++)
	  cin>>r[i];
	for(ll i=1;i<=m;i++)
	  cin>>d[i]>>s[i]>>t[i];
	ll x=1,y=m;
	if(pd(m)){
		cout<<"0"<<'\n';
		exit(0);
	}
	else{
		while(x<y){
			ll mid=(x+y)/2;
			if(pd(mid))
			  x=mid+1;
			else
			  y=mid;
		}		
	}
	cout<<"-1"<<'\n'<<x<<'\n';
	return 0;
} 

Summarize:

  In this question, we have seen the application of difference and prefix sum. Since both difference and prefix sum are fine, then we can warmly welcome the line segment tree (the tree shape seems to be okay? )...

Topic link:

[NOIP2012 Improvement Group] Borrowing Classroom - Luogu https://www.luogu.com.cn/problem/P1083#sub

Guess you like

Origin blog.csdn.net/wo_ai_luo_/article/details/131174092