题解:CF2201B Recollect Numbers
队友知道我喜欢做构造题,于是总是给我推各种构造。然而很不幸的是,这是一道大水题。
题目给了一种贪心的翻翻牌策略,然后让你构造出一种方案使得恰好
首先先无脑地确定下界。显然最优情况下为
【结论 1】 一张牌最多只会被翻两次,并且第二次被翻到时一定会被消掉。
根据贪心策略,一张牌在第一次翻到后就会被记住,因此第二次去翻它时一定进行消除操作。
【结论 2】 上界应为
一次翻牌操作如果没有消去任何的牌,那么就会使得数字为
x ,y 的牌被记住。假设x 未出现过,y 出现过,那么就需要额外花费一次翻牌的机会来消去y 。而初始时不会出现这种情况,因此一次翻牌会消去一种牌或者记住这两张牌所对应的数字。因此上界为2 \times n - 1 ,构造为\{1,2,1,3,2,\ldots,n,n - 1,n\} 。
因此综上所述,
代码如下:
void solve ()
{
int n = read (),k = read ();
vector <int> ans;
if (k < n || k >= 2 * n) {puts ("No");return;}
puts ("Yes");
ans.push_back (1);
for (int i = 2;i <= k - n + 1;++i) ans.push_back (i),ans.push_back (i - 1);
ans.push_back (k - n + 1);
for (int i = k - n + 2;i <= n;++i) ans.push_back (i),ans.push_back (i);
for (auto v : ans) printf ("%d ",v);
puts ("");
}