23.5 杂题
Posted Gemini7X の blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23.5 杂题相关的知识,希望对你有一定的参考价值。
CF543E Listening to Music
先稍微转换问题,对于所有 \\(a_i<x\\),相当于给所有 \\(\\in [i,\\min(i+m-1,n)]\\) 的右端点答案加一。最后就是求一个区间 \\(\\min\\)。于是有一个离线扫描线的 \\(n\\log n\\) 做法。可持久化+标记永久化,可以做到 \\(O(n\\log n)\\) 时空。考虑分块。
对于散块询问,我们需要知道的是块首的值。如果直接预处理是 \\(O(n\\sqrtn)\\) 空间的。考虑继续平衡复杂度,对操作继续分块。那么就相当于有 \\(O(\\sqrtn)\\) 个区间加,做一次区间查 \\(\\min\\)。差分一下复杂度就平衡下来了。
对于整块查询,由于整块加法是平凡的,我们只需考虑散块加法。而对于一个修改,散块加法只有 \\(O(1)\\) 次。于是在修改的时候对散块重构,重新记录散块的 \\(\\min\\) 即可。
CF1824A LuoTianyi and the Show
假设已经有一个人了(没有就分别当 \\(0\\) 或 \\(m+1\\) 有一个人),那么一类和二类都可以结合三类按照顺序往这个人的左边/右边放。如果有一个三类就暂时给三类让路。这样子可以 \\(O(1)\\) 判断。于是枚举第一个加入的三类人即可。
CF1824B LuoTianyi and the Floating Islands
对于奇数,这样的点显然只有一个。而对于偶数,对于一条边,如果两边数量均为 \\(m\\) 这条边两个端点均可。于是对于每条边在下面的端点计数 \\(\\binomsz_um/2\\times \\binomn-sz_um/2\\)。最后每组都少算了一个端点,加个一即可。
LuoTianyi and XOR-Tree
[正睿集训2021] 杂题再讲
你没看错就是 \\(2021\\) 年的题,他就是诈尸了。
Bank Security Unification
题目描述
给定长度为 \\(n\\) 的数列,希望您从中选出一个子序列,使得相邻两项按位与之和最大。
\\(2\\leq n\\leq 10^6,a_i\\leq 10^12\\)
解法
首先不难想到一个 \\(dp\\),设 \\(dp[i]\\) 表示考虑前 \\(i\\) 个数,子序列的结尾是 \\(a_i\\) 的最大权值。
考虑这样一个 \\(\\tt observation\\):如果 \\(a_j\\) 和 \\(a_k\\) 的最高位相同,并且 \\(j<k\\),那么从 \\(k\\) 转移一定比从 \\(j\\) 转移更优,这是因为 \\(a_i\\and a_k+a_k\\and a_j\\geq a_i\\and a_j\\)
这说明了对于每个数位我们只需要保留离 \\(i\\) 最近的一个数,把他们存下来暴力转移时间复杂度 \\(O(n\\log n)\\)
#include <cstdio>
#include <iostream>
using namespace std;
const int M = 1000005;
#define int long long
int read()
int x=0,f=1;char c;
while((c=getchar())<\'0\' || c>\'9\') if(c==\'-\') f=-1;
while(c>=\'0\' && c<=\'9\') x=(x<<3)+(x<<1)+(c^48);c=getchar();
return x*f;
int n,a[M],p[M],dp[M];
signed main()
n=read();
for(int i=1;i<=n;i++)
a[i]=read();dp[i]=dp[i-1];
for(int j=0;j<40;j++) if(p[j])
dp[i]=max(dp[i],dp[p[j]]+(a[i]&a[p[j]]));
for(int j=0;j<40;j++)
if(a[i]&(1ll<<j)) p[j]=i;
printf("%lld\\n",dp[n]);
以上是关于23.5 杂题的主要内容,如果未能解决你的问题,请参考以下文章