20220412

binary

我们观察一下容易发现由于这个 \(y\) 的与是我们去钦定的 ,所以如果与成 \(y\) 的数的个数大于了某个界限那么可以发现 \(y\) 就必定是 \(0\)

我们看一下数的值域是 \(10^9\) ,那么数的总个数如果 \(> 30\) 了我们总是能够找到一种方法使得 \(y\) 变成 \(0\) (通过观察subtask的设置也可以得到结论 ,虽然从赛后结果来看是 \(> 15\) ?)

于是我们现在就把 \(y\) 的限制去掉 ,只需要使 \(x\) 最大 ,这种位运算的题我们容易想到按位贪心

我们设当前的答案是 \(ans\) ,我们已经查看过了前 \(i\) 位答案是否能取到 ,那么我们设 \(chk(x)\) 用于检验 \(x\) 是否能被作为答案 ,那么我们在加入某一位的时候只需要看看 \(x|(1<<i)\)\(chk\) 值是否为 \(1\) 就行了(好像这种才是经典按位取的贪心做法 ,我本来想的是转成二分图连边结果根本做不出来)

考虑这个 \(chk\) 我们可以对于每一个值 ,都容易地算出来它所对应的需要的值是多少 ,然后直接用 \(map\) 维护 \(cnt\)\(min\) 加起来就好了 ,时间复杂度 \(O(n \log^2 n)\)

string

典型的一看就会 ,一做就废

我们考虑设 \(f[i]\) 表示考虑完前 \(i\) 位 ,使得 \(s\)\(t\) 匹配的最小代价

考虑转移 ,第一种非常显然就是如果这一位不相同我们给这一位异或 \(1\) 使得它们相同从 \(f[i-1]\) 加上代价转移过来

考虑如果是交换位置 ,我们设 \(pre[i]\) 表示前缀 \(s\)\(1\) 的个数减去前缀 \(t\)\(1\) 的个数的值

那么我们可以发现一个位置 \(i\) 从交换转移过来的一定是 $max_{j=1}^{i-1} [pre[i]==pre[j]] j $

这是为什么呢 ?我们可以发现如果从这个位置转移过来那么 \(s\) 中的 \(1\) 对应的在 \(t\) 中的位置 ,它们的移动方向都是一定的 ,所以就相当于按照移动方向分段转移(妙啊),于是直接前缀和就好了 ,时间复杂度 \(O(n)\)

eval

主要是没看懂那个 \(x\) 到底是啥意思(可能就是每个数最多出现一次?),如果是按照我理解的意思的话那么直接将 \(n\) 按照十进制分解 ,然后由于还有数的个数限制我们把那些大于一半的强制进位就好了 ,时间复杂度 \(O(k)\)\(k\)\(n\) 的位数)

看完题解后的upd

\(T1\) 原来只是数据造水了 ,实际上 \(n=16\) 是需要特判的不能直接令 \(y=0\) 而且如果有 \(k\) 个数那么每次至少能消掉 \(\lceil \frac{k}{3} \rceil\) 位所以结论才是对的😓

\(T2\) 入手点应该从分离三种操作开始 ,这很像某个 \(JOISC\) 的题 ,一定存在一种最优的操作序列使得我们可以先进行赋值操作再进行交换操作 ,证明手玩一下即可 ,然后题解里如是写道 “在通过手玩以后我们可以发现一个操作序列能够满足不存在一个位置即被赋值过 ,又被翻转过” ,于是这就解释了上面的 \(dp\) 为啥那样直接做是对的

posted @ 2022-04-12 16:21  KJGKMTZB  阅读(68)  评论(0编辑  收藏  举报