首页 > 其他分享 >LOJ #6564 - 最长公共子序列(bitset 求 LCS)

LOJ #6564 - 最长公共子序列(bitset 求 LCS)

时间:2023-04-20 16:56:14浏览次数:62  
标签:LCS LOJ 6564 差分 int MAXN bitset 数组 dp

怎么全天下就我没见过?被薄纱了/ll

还是考虑从朴素的 DP 入手优化。不难发现对于固定的 \(i\),相邻的 \(dp_{i,j}\) 的差要么是 \(0\) 要么是 \(1\),也就是说从压位的考虑角度可能很有前途。因此我们转而维护 \(dp_{i,j}\) 的差分数组 \(v_{i,j}=dp_{i,j}-dp_{i,j-1}\)。考虑新添加一个元素 \(a_{i+1}\) 时候会发生什么变化:对于原来差分数组中每一段极长的连续段 \([l,r]\) 满足 \(v_{i,l}=v_{i,l+1}=\cdots=v_{i,r-1}=0,v_{i,r}=1\),如果 \(b_l,b_{l+1},\cdots,b_{r-1}\) 中存在至少一个元素 \(=a_{i+1}\),那么我们拎出最靠左的那个,假设为 \(b_j\),那么变化是 \(v_{i+1,j}\) 变为 \(1\),\(v_{i+1,r}\) 变为 \(0\),否则这段的差分数组保持不变。

但是不好用 bitset 直接表示。考虑将其转化为可以用 bitset 直接维护的操作:

  • 令 \(f\) 表示原来的差分数组,\(g\) 表示 \(f\) 向右平移一位的数组(即 \(g_{i+1}=f_i,g_1=1\))
  • 令 \(f'\) 为将所有匹配位置变为 \(1\) 后的数组,即对于所有 \(b_j=a_{i+1}\),\(f'_j=1\),其余 \(f'_j=f_j\)。
  • 令 \(g'=f'-g\),其中减法为二进制整数的减法,即将一个 01 数组看作一个大数,其中第 \(i\) 位上的值为该数 \(2^i\) 位上的值。
  • 那么我们再令 \(f'\) 每一位上的值与上 \((f'_i\oplus g'_i)\),就是新的差分数组。

手玩一下就会发现上述过程与 DP 部分所述过程等价。

手写 bitset 即可。时间复杂度 \(\dfrac{nm}{\omega}\)。

const int MAXN=70000;
const int B=MAXN/64+1;
int n,m,a[MAXN+5],b[MAXN+5];
u64 pos[MAXN+5][B+5],f[B+5],g[B+5],h[B+5];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)scanf("%d",&b[i]);
	for(int i=1;i<=n;i++)pos[a[i]][i>>6]|=(1ull<<(i&63));
	for(int i=1;i<=m;i++){
		memset(g,0,sizeof(g));memset(h,0,sizeof(h));
		for(int j=0;j<=B;j++)g[j]|=f[j]<<1,g[j+1]|=(f[j]>>63&1);
		g[0]|=2;
		for(int j=0;j<=B;j++)f[j]|=pos[b[i]][j];
		u64 c=0;
		for(int j=0;j<=B;j++){
			h[j]=f[j]-g[j]-c;
			c=(c&&(f[j]==0))||((u64)(f[j]-c)<g[j]);
		}
		for(int j=0;j<=B;j++)f[j]&=(f[j]^h[j]);
	}
	int sum=0;
	for(int i=0;i<=B;i++)sum+=__builtin_popcountll(f[i]);
	printf("%d\n",sum);
	return 0;
}

标签:LCS,LOJ,6564,差分,int,MAXN,bitset,数组,dp
From: https://www.cnblogs.com/tzcwk/p/LOJ-6564.html

相关文章

  • 关于 Angular 12 的 inlineCriticalCss 选项
    inlineCriticalCss是Angular项目中的一个配置选项,用于指定是否将关键CSS内联到页面HTML中。通常情况下,网页中的CSS文件是由浏览器异步加载的,这意味着在浏览器加载完HTML后还需要额外的时间来加载CSS文件,这会导致页面的首次渲染时间较长,用户体验不佳。为了解决这个问......
  • [loj3408]lancllords
    考虑归并排序,问题即如何合并两个序列\(A,B\)不妨假设\(|A|>|B|\),将\(A\)按下标奇偶性划分为\(A_{0}\)和\(A_{1}\)将\(A_{0}\)与\(B\)归并,得到序列\(C\)对于\(A_{1}\)中的元素,仅需与(\(C\)中)\(A_{0}\)中相邻两数间的\(B\)中元素比较比较次数为\(|B|\),用莫队实现,操作次数为......
  • Error response from daemon: conflict: unable to remove repository reference "mic
    docker删除镜像时出现了这样的问题解决方法:强制删除docerrmi-f[IMAGEID]......
  • loj6144「2017 山东三轮集训 Day6」C
    loj6144「2017山东三轮集训Day6」C注意到修改只有位运算,容易想到将位拆开考虑。首先可以发现对某一位或上\(0\)或者是对某一位与上\(1\)是没有意义的,相当于没有操作......
  • [loj3931]楼梯
    注意到边界格数\(=\)(左上)轮廓线长度\(-1=\)(右下)轮廓线长度\(-1\)问题即在整体(右下)轮廓线中选连续\(q+1\)条,满足第一条为竖线且最后一条为横线将两者分别标记为\(01\),即对......
  • 【LOJ 3378】点格棋(DP)(推论)
    点格棋题目链接:LOJ3378题目大意有一个(n+1)*(m+1)的格点组成的网格,然后两个人轮流操作,选两个相邻(距离为1)且没有连边的点对连一个竖直或者水平的线段。然后如果一个......
  • [loj6868]种苹果
    在树上随机选\(K\)个点,并建立虚树,称虚树上的点为关键点结论:一个点到关键点最近距离的期望为\(O(\frac{n}{K})\)将所有点按到其距离排序,最坏情况即链的端点,此时结论是经......
  • loj3076
    参照E_Space的候选队论文,我们建出广义串并联图进行「删一度点」「缩二度点」「叠合重边」操作合并信息的表达式树。我们把其描述成一颗LeafyTree。我们不妨在每个叶......
  • LOJ 3276 JOISC 2020 Day2 遗迹 题解 (计数DP)
    LOJ链接UOJ链接观察一下n次地震的过程,发现最后会有n个石柱高度为0,\(1,2\cdotsn\)高度的石柱各有一个。假设现在已经确定了一种初始高度状态,我们来看看最后哪些石柱高度......
  • 题解 LOJ P2393 「JOISC 2017 Day 2」门票安排
    题意咕咕咕。题解这题太神了,无限膜拜p_b_p_b,搬运一波题解。首先考虑二分。题意等价于选一些区间进行反转。首先注意到反转的区间两两有交,不然不反转一定更优。设反转......