P2418「yyy loves OI IV」

Posted by prc on Tue, 01 Mar 2022 09:43:00 +0100

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;
}