题目大意:
n个节点,选择一个节点的时候翻转这个节点与两侧k个节点(够的话),求最少几次全部翻到反面。
ps:同一个节点翻两次会翻回正面。
思路:
贪心,尽量多的选能翻翻2k+1个节点的节点,即在中间尽量多的划分长度为2k+1的区间。为使中间节点数恰好为(2k+1)的整数倍,两侧特殊考虑。
在边上最少翻k+1块,最多2k+1,故两边留的总节点数d要满足 2k+1d
4k+2
当2k+2d
3k+2时,一侧取k+1的最小情况,一侧根据剩余节点选择;
当3k+2d
4k+2时,一侧去2k+1的最大情况,一侧根据剩余节点选择。
若找不出这个范围内的d,直接输出中点即可
#include<bits/stdc++.h>
using namespace std;
vector<int> ans;
int main()
{
int n,k; scanf("%d%d",&n,&k);
int d = n%(2*k+1);
int t = n/(2*k+1);
while(d<=n){
d+=2*k+1;
if(d>=2*k+2&&d<=4*k+2) break;
}
if(d>=2*k+2&&d<=4*k+2&&d<=n){
ans.clear();
if(d<=3*k+2){
int l = d - 2 * k - 1;
while(l<=n){
ans.push_back(l);
l += 2 * k + 1;
}
}
else{
int l = d - 3 * k - 1;
while(l<=n){
ans.push_back(l);
l += 2 * k + 1;
}
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++) printf("%d ",ans[i]);
printf("\n");
}
else{
printf("1\n%d\n",(n+1)/2);
}
}