Descriptionios
【题目背景】
LHX教主身为宇宙第一富翁,拥有一栋富丽堂皇的别墅,因为别墅实在太大了,因而教主雇佣了许许多多的人来负责别墅的卫生工做,咱们不妨称这些人为LHXee。web
【题目描述】
教主一共雇佣了N个LHXee,这些LHXee有男有女。
教主的大别墅一共有M个房间,如今全部的LHXee在教主面前排成了一排。教主要把N个LHXee分红刚好M个部分,每一个部分在队列中都是连续的一段,而后分别去打扫M个房间。
教主身为全世界知识最渊博的人,他固然知道男女搭配干活不累的道理,以及狼多羊少,羊多狼少的危害之大。因此教主但愿一个分配方式,使得全部小组男女个数差的最大值最小。
教主还但愿你输出从左到右,每一个组的人数。
若是有多种人数组合都能达到最优值,教主但愿你分别告诉他这些方案中字典序最小和最大的方案。换句话说,你须要找到两种方案,这两种方案知足全部组男女个数差最大值最小的前提下,第一种方案(字典序最小)要越靠前的组人数越少,也就是让第一个小组人尽可能少,而且在第一个小组人尽可能少的前提下,让第二个小组的人尽可能少,依此类推;第二种方案(字典序最大)则要让越靠前的组人数越多。数组
Input
输入的第1行为两个正整数N与M,用空格分隔。
第2行包含一个长度为N的串,仅由字符组成,第i 个字符为0表示在这个位置上的LHXee为女生,若为1则为男生。svg
Output
输出文件包含两行,每行M个正整数,正整数之间用空格隔开,行末无多余空格。这M个正整数从左到右描述了你所分的每一个组的人数。
第1行为字典序最小的方案,第2行为字典序最大的方案。
【数据规模】
对于40%的数据,有N ≤ 100;
对于50%的数据,有N ≤ 1000;
对于65%的数据,有N ≤ 100000;
对于100%的数据,有N ≤ 5000000,M ≤ N且M ≤ 100000。ui
贪心:
先求出男女生的差值尽可能平均分配到m个房间.【ans】
用O(n)的时间扫一遍即得答案.【注意还要倒着算一次最小字典序】
注意:差值为0(即男女生人数同样的时候)要特殊处理;
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
int n,m,ans,k,a[5000001],b[5000001]; char c;
int abs(int x)
{ if (x>=0) return x; else return -x; }
int main()
{
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;i++)
{
cin>>c;
if (c=='1') a[i]=a[i-1]+1; else a[i]=a[i-1]-1; //前缀和
}
ans=abs(a[n])/m; //ans
if (a[n]%m!=0) ans++; //向下取整
if (a[n]==0) //处理特殊状况
{
k=0;
for (int i=1;i<=n;i++)
if (a[i]==0) k++;
if (k>=m) ans=0; else ans=1;
}
int next=0,t=m; //next记录上一次分割的位置
for (int i=1;i<=n;i++)
{
k=abs(a[n]-a[i])/(t-1); //分割i-next这一部分,后面剩余的男女生的差值尽可能平均分值
if (((abs(a[n]-a[i]))%(t-1))!=0) k++; //等同ans的处理
if (k<=ans&&(abs(a[i]-a[next])<=ans))//若是男女生的差值尽可能平均分都容许的话就输出
{
printf("%d ",i-next);
next=i;
t--;
if (t==1) //只剩下一份的状况
{
printf("%d ",n-next); //直接输出
break;
}
}
}
printf("\n");
next=n; t=m; int o=0;
for (int i=n-1;i>=1;i--)//倒着再处理一次
{
k=abs(a[i])/(t-1);
if ((abs(a[i]))%(t-1)!=0) k++;
if ((abs(a[next]-a[i])<=ans)&&k<=ans)
{
b[++o]=next-i; //要用b数组储存起来,由于要再倒着输出
next=i;
t--;
if (t==1)
{
b[++o]=next;
break;
}
}
}
for (int i=o;i>=1;i--)
printf("%d ",b[i]);
}