构造你值得拥有
构造题是比赛中常见的一类题型。
从形式上来看,问题的答案往往具有某种规律性,使得在问题规模迅速增大的时候,仍然有机会比较容易地得到答案。
这要求解题时要思考问题规模增长对答案的影响,这种影响是否可以推广。例如,在设计动态规划方法的时候,要考虑从一个状态到后继状态的转移会造成什么影响。
构造的特点
构造题一个很显著的特点就是高自由度,也就是说一道题的构造方式可能有很多种,但是会有一种较为简单的构造方式满足题意。看起来是放宽了要求,让题目变的简单了,但很多时候,正是这种高自由度导致题目没有明确思路而无从下手。
构造题另一个特点就是形式灵活,变化多样。并不存在一个通用解法或套路可以解决所有构造题,甚至很难找出解题思路的共性。
对于一些比较容易写出小范围暴力的构造题,在比赛时如果时间充足可以考虑打表观察规律。
构造的例题
给定一个长度为 nnn、元素由 000 或 111 组成的数组。
现在可以选择若干(可以为 000)个值为 000 的元素,将其修改为 111。
记:xxx 为数组中最长连续 111 子段的长度(规定,若所有数均为 000,则 xxx为 000);yyy 为修改的元素的个数。
求要怎么修改才能使 x−yx−yx−y 最大,并构造一个方案(输出修改后的数组)。
每次只要枚举查看左边和右边是否有111,有的话就把当前下标设为111,然后yyy++。
#include<bits/stdc++.h>
using namespace std;
bool f[100005];
int main(){
int t;
cin>>t;
while(t--){
memset(f,0,sizeof f);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>f[i];
}
int y=0;
for(int i=1;i<=n;i++){
if(!f[i]&&(f[i-1]||f[i+1])){
f[i]=1;
y++;
}
}
int mx=0,cs=0;
for(int i=1;i<=n;i++){
if(f[i]){
cs++;
}else{
cs=0;
}
mx=max(mx,cs);
}
cout<<mx-y<<endl;
for(int i=1;i<=n;i++){
cout<<f[i]<<" ";
}
cout<<endl;
}
return 0;
}