1. Title
Title Link: P2418「yyy loves OI IV」 .
Topic background
There are two OI cows in a school in 2015, yyy and c01.
Title Description
All the N students in the school except them will worship one of them. Now the teacher will assign them dormitories. But here comes the problem:
People in the same dormitory either worship the same Daniel, or the absolute difference between yyy and c01 is no more than M. Or they'll fight.
For convenience, the teacher asked N students to stand in a row. Only those who stand together continuously can be divided into the same dormitory.
Assuming that each dormitory can accommodate any number of people, how many dormitories should be arranged at least?
Input format
First line, two positive integers N and M.
Line 2 \cdots N+1, with an integer 1 or 2 in each line. The number in line i represents the Daniel worshipped by the i-1 person from left to right.
1 means yyy and 2 means c01.
Output format
One line, an integer, indicates that at least several dormitories should be arranged.
Sample input and output
Enter #1
5 1 1 1 2 2 1
Output #1
1
Description / tips
Difficult questions, be prepared ~
2. Problem solving
analysis
Start from the first classmate and gradually scan to the last classmate; It is easy to know that except for the last dormitory, other dormitories:
- Or all worship the same big man
- Or the difference between the absolute values of M
Let dp[i] represent the minimum number of dormitories required by the first I students after processing, stu[i] represent the leaders worshipped by the first I students (− 1 represents 1, 1 represents 2), sum[i] = \sum stu[i] represent the algebraic sum of the leaders worshipped by the first I students (i.e. the difference between the number of two leaders worshipped, which is the reason why 1 and 2 are mapped to − 1 and 1: convenient processing), ump[u] indicates the minimum number of dormitories required for the current input when the absolute value of the difference between the number of worshippers and worshippers is u (because the value range of u is large, choose unordered_map to store records).
[note] the reason why ump[u] can be set is that in the best case, the situation of all dormitories is the same, that is, the same big man has the largest number of worshippers (otherwise, since there is no upper limit on the number of dormitories, different dormitories with a large number of adjacent worshippers can be combined, which still meets the conditions of the question).
- For the first case: it can be realized by setting the position of a different record value on the record; That is \ leq dp[last] + 1, where last is the position of the last classmate relative to the boss worshipped by classmate i. That is, the number of dormitories for the current students is at most 1 more than that of the previous students with different beliefs (because at this time, the students between the two worship the same boss).
- For the second case: \ leq ump[abs(sum[i]) - M] + 1, that is, the minimum number of dormitories required when there are at least m fewer than now + 1.
Therefore, for u \leq 0, ump[u] = 0. Because abs(sum[i]) - M \leq 0 indicates that the difference between the number of worshippers and the number of worshippers does not exceed m, at most one dormitory is required at this time, that is, ump[abs(sum[i]) - M] = 0.
Combining the two, the state transition equation can be listed: dp[i]=min(dp[last]+1,ump[abs(sum[i]) − M]+1). The final result is dp[n].
code
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 5; int stu[MAXN], sum[MAXN], dp[MAXN]; //Ultimate fast reading char buf[1<<22],*p1=buf,*p2=buf; #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1==p2)?EOF:*p1++) //Read quickly inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } void input(int n) { for(int i = 1; i <= n; ++i) { int a = read(); stu[i] = 2*a - 3; } } int myabs(int x) { return x < 0 ? -x : x; } void init(int n) { for(int i = 1; i <= n; ++i) { sum[i] = sum[i-1] + stu[i]; } } unordered_map <int,int> ump; void update(int u, int x) { if(u > 0) { if(ump.count(u) == 0) { ump[u] = x; } else { ump[u] = min(ump[u], x); } } } int query(int u) { if(ump.count(u) == 0) { if(u <= 0) { return 0; } else { return MAXN; } } return ump[u]; } int answer(int n, int m) { int last1 = 0, last2 = 0; for(int i = 1; i <= n; ++i) { if(stu[i] == 1) { dp[i] = dp[last2] + 1; last1 = i; } else { dp[i] = dp[last1] + 1; last2 = i; } dp[i] = min(dp[i], query(myabs(sum[i])-m)+1); update(myabs(sum[i]), dp[i]); } return dp[n]; } int main() { int n, m; scanf("%d%d", &n, &m); input(n); init(n); printf("%d\n", answer(n,m)); return 0; }