Cooking Schedule Problem Code: SCHEDULE
As you might know, cooking is not an easy job at all and cooking everyday makes the chef very tired. So, Chef has decided to give himself some days off.
Chef has made a schedule for the next N days: On i-th day if Ai is equal to 1 then Chef is going to cook a delicious dish on that day, if Ai is equal to 0 then Chef is going to rest on that day.
After Chef made his schedule he discovered that it's not the best schedule, because there are some big blocks of consecutive days where Chef will cook which means it's still tiring for Chef, and some big blocks of consecutive days where Chef is going to rest which means chef will be bored doing nothing during these days.
Which is why Chef has decided to make changes to this schedule, but since he doesn't want to change it a lot, he will flip the status of at most K days. So for each day which Chef chooses, he will make it 1 if it was 0 or he will make it 0 if it was 1.
Help Chef by writing a program which flips the status of at most K days so that the size of the maximum consecutive block of days of the same status is minimized.
Input
The first line of the input contains an integer T denoting the number of test cases.
The first line of each test case contains two integers: N denoting the number of days and K denoting maximum number of days to change.
The second line contains a string of length N , of which the i-th character is 0 if chef is going to rest on that day, or 1 if chef is going to work on that day
Output
For each test case, output a single line containing a single integer, which is the minimum possible size of maximum block of consecutive days of the same status achievable.
Constraints
- 1 ≤ T ≤ 11,000
- 1 ≤ N ≤ 106
- The sum of N in all test-cases won't exceed 106.
- 0 ≤ K ≤ 106
- 0 ≤ Ai ≤ 1
Subtasks
- Subtask #1 (20 points): N ≤ 10
- Subtask #2 (80 points): Original Constraints
Example
Input: 2 9 2 110001111 4 1 1001 Output: 2 2 思路:
用大根堆存连续相同序列的长度,同时存下标号及切割次数(为了在最长的连续序列相同的前提下先切切割次数少的,因此要先用一个大一些的数代表切割0次,每切割一次这个数减1),用另一个数组记录这个序列的最初长度。每次切割长度最长的序列,长度变成最初的长度/(切割次数+1),再次加进堆(只需加一段即可)。直到剩下的最长长度只有2。对于小于2的情况,特殊处理即可。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<algorithm> #include<cstring> #include<string> #include<vector> #include<map> #include<set> #include<queue> using namespace std; int _; int n,k,a[1000001]; char c[1000001]; priority_queue <pair<int,pair<int,int>>> q; int main() { scanf("%d",&_); while (_--) { scanf("%d%d",&n,&k); scanf("%s",c); while (!q.empty()) q.pop(); int tot=1,cnt=1;; int i; for (i=1;i<n;i++) if (c[i]==c[i-1]) tot++; else { //cout<<tot<<endl; q.push({tot,{100000,cnt}}); a[cnt]=tot; cnt++; tot=1; } q.push({tot,{100000,cnt}}); a[cnt]=tot; cnt++; if (q.top().first==1) { puts("1"); continue; } char p='1'; tot=0; int len=strlen(c); for (i=0;i<len;i++) { if (c[i]!=p) tot++; if (p=='1') p='0'; else p='1'; } if (tot<=k) { puts("1"); continue; } p='0'; tot=0; for (i=0;i<len;i++) { if (c[i]!=p) tot++; if (p=='1') p='0'; else p='1'; } if (tot<=k) { puts("1"); continue; } //cout<<"hhhhhhhhhh"<<endl; //cout<<q.top()<<endl; int x; while (k--) { x=q.top().first; if (x<=2) break; int ix=q.top().second.second; int nval=a[ix]; int id=q.top().second.first; id--; int im=100000-id; x=nval/(im+1); q.pop(); q.push({x,{id,ix}}); } printf("%d ",q.top().first); } return 0; }