首页 > 其他分享 >[CF1392G] Omkar and Pies

[CF1392G] Omkar and Pies

时间:2024-07-06 17:30:28浏览次数:4  
标签:CF1392G kk 复杂度 元素 异或 Omkar FWT Pies getchar

还是记一下这个 trick 吧,虽然很简单但是我认为十分有趣!本质上是 Maximize the Difference 做法的扩展。(似乎有人称作 RainFestivalTree???)

这个题经过一些简单转化可以转化为这样一个问题:给定有二进制数序列 \(A,B\),求 \(\max_{r-l\ge m} |A_l\oplus B_r|\)(\(|x|\) 即二进制位下一的个数,\(\oplus\) 是异或)。

由于这个题有特殊性质,即序列 \(A,B\) 中所有元素的 popcount 都相等,所以我们只关注 \(|A_l\cap B_r|\),所以绝大多数题解给出了一个基于普通高维后缀和的 \(O(k2^k)\)。

但是假设序列 \(A,B\) 没有任何特殊性质,这个题仍然可以做!我们考虑到异或信息也是可以 FWT 的,我们给 FWT 数组再开一维记录 popcount,合并的时候更新一下,就扩展到了序列任意的情况。这也是环一周和叉老师在模拟赛场上的写法,复杂度为 \(O(2^kk^2)\),空间复杂度 \(O(2^kk)\)。

那我场上又写了个啥抽象玩意呢?事实上,对于上面这个问题,我们可以做到在线维护!

这个做法的基本思想是对于一般的 FWT 问题,假设你要增量维护其结果,你可以暴力 dfs 子集/超集,遇到已经访问了的就回退,这样每个集合只会被增广一次。

那么对于此题中的多带了一维的异或 FWT,其也可以施加暴力 dfs 的技巧。具体地,我们增量维护一个集合 \(S\),并记录 \(f\) 数组表示对于所有长为 \(k\) 数到 \(S\) 中数的最小汉明距离,即 \(f_x=\min_{y\in S} |x\oplus y|\)。

每次往 \(S\) 加入一个元素 \(x\) 时,我们暴力 dfs 这个元素的邻域,如果当前元素 \(y\) 到 \(x\) 的距离不小于 \(f_y\) 就直接返回。这样,对于每一个元素,其 \(f\) 只会至多被更新 \(O(k)\) 次,每次更新至多耗费 \(O(k)\) 的时间复杂度。总时间复杂度也是 \(O(2^kk^2)\),但空间做到了 \(O(2^k)\) 且可以强制在线。

如果到当前元素汉明距离比当前答案还大的话还可以剪枝,数据基本不可能卡满而且除了一堆常数,所以事实上这个算法竟然能跑过一大堆 \(O(2^kk)\)。

#include <cstdio>
using namespace std;
int read(){
	char c=getchar();int x=0;
	while(c<48||c>57) c=getchar();
	do x=x*10+(c^48),c=getchar();
	while(c>=48&&c<=57);
	return x;
}
const int N=10000003,K=20,INF=0x3f3f3f3f;
int n,m,k,o;
int res=INF,ix=-1,iy=-1;
int f[1<<K],ps[1<<K];
bool vis[1<<K];
int px[N],py[N],p[N];
int A[N],B[N];
void dfs(int s,int d,int lim){
	if(d>=res||f[s]<=d) return;
	f[s]=d;
	if(ps[s]>=o+m) res=d,ix=o,iy=ps[s];
	for(int i=lim;i<k;++i) dfs(s^(1<<i),d+1,i+1);
}
int main(){
	n=read();m=read();k=read();
	char cc=getchar();
	while(cc!='0'&&cc!='1') cc=getchar();
	for(int i=0;i<k;++i){
		if(cc=='1') A[n+1]|=(1<<i);
		cc=getchar();
	}
	while(cc!='0'&&cc!='1') cc=getchar();
	for(int i=0;i<k;++i){
		if(cc=='1') B[n+1]|=(1<<i);
		cc=getchar();
	}
	for(int i=0;i<k;++i) p[i]=i;
	for(int i=1;i<=n;++i) px[i]=read()-1,py[i]=read()-1;
	for(int i=n;i;--i){
		int X=p[px[i]],Y=p[py[i]];
		p[px[i]]=Y;p[py[i]]=X;
		px[i]=X;py[i]=Y;
	}
	for(int i=n;i;--i){
		A[i]=A[i+1];B[i]=B[i+1];
		if(((A[i]>>px[i])^(A[i]>>py[i]))&1) A[i]^=(1<<px[i])^(1<<py[i]);
		if(((B[i]>>px[i])^(B[i]>>py[i]))&1) B[i]^=(1<<px[i])^(1<<py[i]);
	}
	for(int i=1;i<=n+1;++i) ps[B[i]]=i;
	for(int s=0;s<(1<<k);++s) f[s]=INF;
	for(o=1;o<=n+1;++o) dfs(A[o],0,0);
	printf("%d\n%d %d\n",k-res,ix,iy-1);
	return 0;
}

标签:CF1392G,kk,复杂度,元素,异或,Omkar,FWT,Pies,getchar
From: https://www.cnblogs.com/yyyyxh/p/18287478/CF1392G

相关文章

  • B. Omkar and Heavenly Tree
    原题链接题解真的bt啊由于m没有限制所有测试用例的总和,所以m可以近似看为1e9,也就是说,除了输入以外,不能有任何对m的处理(常数乘上1e9)考虑菊花图,任意两点之间最多只有一个陌生点,而且\(m\ltn\)所以找出那个没有出现过的中间点,作为菊花图的中心md!!构造题!!code#include<bits/std......
  • CF1372F Omkar and Modes 题解
    来个乱搞。思路考虑分治。对于最裸的暴力。我们可以调用solve(l,r)进行查询。假如这个区间的众数的出现次数是区间长度,那么可以直接退出,否则我们可以继续分治。我们把这个暴力进行加工一下。我们知道\(l\simr\)的区间众数后。查询\(l\simmid\)的区间众数,若完全......
  • CF1536F Omkar and Akmar 题解
    思路首先最后的局面在两两字母间一定不会多于\(1\)个空格。考虑反证,假设有两个空格,那么有以下两种情况:\(\text{A}\_\_\text{B}\),\(\text{A}\_\_\text{A}\),也就是两边的字母不同,相同。对于第一种,在任意一个空格都可以填一个与他相邻字符不同的字符,对于第二种,填\(\text{B}\)......
  • Omkar and Akmar 题解
    题意:有一个\(n\)个点的环,以及两个人。每个人可以向环中任意一个位置放置一个\(A\)或者\(B\),但是相邻的位置不能相同,不能行动者输。问最终的局面有多少种。一个结论是:后手必胜。证明:最终肯定不可能出现两个连续的空格,否则一定可以在其中一个上填\(A\)或\(B\)。所以最多只......
  • papamelon 302. 碰撞游戏 Stripies(挑战程序设计竞赛)
    地址https://www.papamelon.com/problem/302http://poj.org/problem?id=1862解答自取了几个样例从大到小和从小到大进行模拟发现最大的数最先碰撞则开方的次数最多,所以需要结果最小,则优先去最大的数进行合并。代码如下#include<iostream>#include<algorithm>#includ......
  • pieslice(),setcolor(),setbkcolor()
    #include<graphics.h>#include<stdio.h>intmain(){inti;intgraphdriver=DETECT;intgraphmode;initgraph(&graphdriver,&graphmode,"");cleardevice();setcolor(4);setbkcolor(BLUE);pieslice(200,200,0,90,100);rectangle(301,......
  • Moves, copies and clones in Rust
    原文链接:Moves,copiesandclonesinRust简介(Introduction)move和copy是Rust中的基础概念。这对于来自Ruby、Python或C#等垃圾回收语言的程序员来说可能是完全陌生的。这些术语在C++中也确实存在,但它们在Rust中的含义却有微妙的不同。在本文中,我将解释对值进行mo......
  • CF #724(div2)A. Omkar and Bad Story,贪心,构造序列
    problemA.OmkarandBadStorytimelimitpertest2secondsmemorylimitpertest256megabytesinputstandardinputoutputstandardoutputOmkarhasreceivedames......
  • CF1536F. Omkar and Akmar
    牛B题首先因为n>=2,可以发现后手必胜:①当n为偶数时,后手跟着先手走对称,按照n和1的分界线作为对称轴,位置对称+棋子反转②当n为奇数时,设先手走x,后手走x+2,按照x+1作为对称......
  • CF1372D Omkar and Circle
    题目传送门思路这是一道非常简单的\(\mathcal*2100\)。既然他样例给的那么简单,说明这是一道结论题。于是我们可以手玩几组数据试试。例如\(3,5,9,8,12\)这组,发现......