#include <bits/stdc++.h>
using namespace std;
const int o = 5e5;
const int N = 5e5+10;
const int INF = 0x3f3f3f3f;
int a[N];
int s[N],dp[N];
int tree[N << 2];
int lazy[N <<2];
int pre[N];
int t[N << 2];
int n,m;
void up(int node, int l, int r, int pos, int val) {
if (l == r) {
t[node] = min(t[node], val);
} else {
int mid = (l + r) >> 1;
if (pos <= mid)
up(node << 1, l, mid, pos, val);
else
up(node << 1 | 1, mid + 1, r, pos, val);
t[node] = min(t[node << 1], t[node << 1 | 1]);
}
}
int qu(int node, int l, int r, int ql, int qr) {
if (r < ql || l > qr) return INF;
if (ql <= l && r <= qr) return t[node];
int mid = (l + r) >> 1;
return min(
qu(node << 1, l, mid, ql, qr),
qu(node << 1 | 1, mid + 1, r, ql, qr)
);
}
bool Inrange(int L,int R,int l,int r){
return (L >= l) && (R <= r);
}
bool Outrange(int L,int R,int l,int r){
return (L > r) || (R < l);
}
void pushup(int node){
tree[node] = min(tree[node << 1],tree[node << 1|1]);
}
int build(int node,int left,int right){
if(left == right){
tree[node] = 0x3f3f3f3f;
}
else{
int mid = (left+right) >> 1;
build(node << 1,left,mid);
build(node << 1|1,mid+1,right);
pushup(node);
}
}
//void up(int idx, int val) {
// for (; idx > 0;) {
// t[idx] = min(t[idx], val);
// idx -= idx & -idx;
// }
//}
//
//int qu(int idx) {
// int res = INF;
// for (; idx <= N; ) {
// res = min(res, tree[idx]);
// idx += idx & -idx;
// }
// return res;
//}
int maketag(int node,int len,int val){
tree[node] = min(tree[node], val);
lazy[node] = min(lazy[node], val);
}
int pushdown(int node,int left,int right){
if(lazy[node] != 0x3f3f3f3f){
int mid = (left + right) >> 1;
maketag(node << 1,mid-left+1,lazy[node]);
maketag(node << 1|1,right-mid,lazy[node]);
lazy[node] = 0x3f3f3f3f;
}
}
int query(int node,int left,int right,int l,int r){
if(Inrange(left,right,l,r)){
return tree[node];
}
else{
if(!Outrange(left,right,l,r)){
int mid = (left+right) >> 1;
pushdown(node,left,right);
return min(query(node << 1,left,mid,l,r) , query(node <<1|1,mid+1,right,l,r));
}
else return 0x3f3f3f3f;
}
}
//void update(int node,int L,int R,int l,int r,long long int val){
// if(Inrange(L,R,l,r)){
// maketag(node,R-L+1,val);
// }
// else{
// if(!Outrange(L,R,l,r)){
// int M = (L+R) >> 1;
// pushdown(node,L,R);
// update(node << 1,L,M,l,r,val);
// update(node << 1|1,M+1,R,l,r,val);
// pushup(node);
// }
// }
//}
void update_point(int node, int left, int right, int pos, int k) {
if (left == right) {
tree[node] = min(tree[node],k);
} else {
int mid = (left + right) >> 1;
if (pos <= mid) update_point(node << 1, left, mid, pos, k);
else update_point(node << 1 | 1, mid + 1, right, pos, k);
pushup(node);
}
}
//int main(){
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
// cin >> n >>m;
// for(int i = 1;i<=n;i++){
// int val;
// cin >>val;
// if(val == 2) val = -1;
// a[i] = val;
// s[i] = s[i-1] +a[i];
// if(a[i] == a[i-1]){
// pre[i] = pre[i-1] +1;
// }
// else pre[i] = 1;
// }
// memset(dp, 0x3f, sizeof(dp));
// dp[0] = 0;
// build(1,1,n);
// update_point(1,1,n,1,dp[0]);
//// for (int i = 1; i <= n; i++) {
//// int min_dp = N;
//// for (int j = max(0,i-100); j < i; j++) {
//// if (s[i] - m <= s[j] && s[j] <= s[i] + m) {
//// min_dp = min(min_dp, dp[j]);
//// }
//// }
//// if (min_dp != N) {
//// dp[i] = min(dp[i], min_dp + 1);
//// }
//// dp[i] = min(dp[i], dp[i - pre[i]] + 1);
//// update_point(1, 1, n, i + 1, dp[i]);
//// }
// for(int i = 1;i<=n;i++){
// int ql = max(-o, s[i] - m);
// int qr = min(o * 2, s[i] + m);
// ql += o;
// qr += o;
// int min_dp = INF;
// for (int j = qr + 1; j > 0; j -= j & -j) {
// min_dp = min(min_dp, t[j]);
// }
// for (int j = ql; j > 0; j -= j & -j) {
// min_dp = min(min_dp, t[j]);
// }
// if (min_dp != INF) {
// dp[i] = min(dp[i], min_dp + 1);
// }
// up(s[i] + o, dp[i]);
// if (min_dp != N) {
// dp[i] = min(dp[i], min_dp + 1);
// }
// dp[i] = min(dp[i], dp[i - pre[i]] + 1);
// update_point(1, 1, n, i + 1, dp[i]);
// }
//
//
//// for(int i = 1;i<=n;i++){
//// for(int j = 0;j<i;j++){
//// if(s[i]-m <= s[j] && s[j] <= m+s[i]){
//// update_point(1,1,n,i,min(dp[i],dp[j]+1));
//// }
//// }
//// update_point(1,1,n,i,min(query(1,1,n,i-pre[i],i-1),dp[i]));
//// }
//// cout << dp[n];
// cout << dp[n];
// return 0;
//}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
int val;
cin >> val;
if (val == 2) val = -1;
a[i] = val;
s[i] = s[i - 1] + a[i];
if (i > 1 && a[i] == a[i - 1]) {
pre[i] = pre[i - 1] + 1;
} else {
pre[i] = 1;
}
}
memset(dp, 0x3f, sizeof(dp));
memset(t,N,sizeof(t));
dp[0] = 0;
up(1, 0, N - 1, s[0] + o, dp[0]);
for (int i = 1; i <= n; ++i) {
int min_dp = qu(1, 0, N - 1,s[i] - m+ o, s[i] + m + o);
if (min_dp != INF) dp[i] = min(dp[i], min_dp + 1);
if (i - pre[i] >= 0) dp[i] = min(dp[i], dp[i - pre[i]] + 1);
up(1, 0, N - 1, s[i] + o, dp[i]);
}
cout << dp[n] << endl;
return 0;
}题目背景
某校 2015 届有两位 OI 神牛,yyy 和 c01。
题目描述
全校除他们以外的 N 名学生,每人都会膜拜他们中的某一个人。现在老师要给他们分宿舍了。但是,问题来了:
同一间宿舍里的人要么膜拜同一位大牛,要么膜拜 yyy 和 c01 的人数的差的绝对值不超过 M。否则他们就会打起来。
为了方便,老师让 N 名学生站成一排,只有连续地站在一起的人才能分进同一个宿舍。
假设每间宿舍能容纳任意多的人,请问最少要安排几个宿舍?
输入格式
第一行,两个正整数 N 和 M。
第 2,3,⋯,N+1 行,每行一个整数,是 1 或 2,第 i 行的数字表示从左往右数第 i−1 个人膜拜的大牛,1 表示 yyy,2 表示 c01。
输出格式
一行,一个整数,表示最少要安排几个宿舍。
输入输出样例
输入 #1复制
5 1
1
1
2
2
1
输出 #1复制
1
最新发布