ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1582F Korney Korneevich and XOR

2021-10-25 09:33:48  阅读:250  来源: 互联网

标签:le XOR 8195 CF1582F 更新 read int Korney qwq


CodeforcesF1
CodeforcesF2
LuoguF1
LuoguF2

Description.

有一个长度为 \(n\) 的序列,求每个严格递增子序列异或值的并。

F1 : \(n\le 10^5,V\le 500\)
F2 : \(n\le 10^6,V\le 5000\)

Solution.

F1 有手就行,直接做,做完了。
大概就是记 \(dp_i\) 表示当前 \(\oplus\) 值为 \(i\) 的点的结束位置最小值。
每次枚举一遍值域就行了,总复杂度 \(O(nV)\) 可以过 F1。


F2 以 \(\oplus\) 值建图。
这张图有 \(O(nV)\) 条边,有 \(O(V^2)\) 个点。
而且是一个分层图,从第一层出发走问能否走到某层的指定顶点。
我们考虑 \(O(V^2)\) 的做法,尝试让 \(O(nV)\) 个冗余状态消失。
考虑一个点,它第一遍被更新肯定是最优的,也就是说,只要一个点被更新过,那它状态就确定了。
那我们考虑只让每个点被更新一次,这样复杂度就真了。
我们考虑那些 \(O(nV)\) 的边其实有性质,都是 \((a,qwq)\rightarrow (a\oplus t,t)\) 的边。
所以如果对 \((a,?)\) 已经向 \((a\oplus t,t)\) 更新过了,那剩下所有边都不需要了。
而且这个边还具有单调性,也就是说每次被更新的肯定是一个后缀(因为 \(t\ge qwq\))。
所以每次更新的肯定是一段区间,然后就可以判断这段区间有没有被覆盖来转移。
均摊一下发现每个点只会被更新 \(1\) 次,总更新失败次数 \(O(n)\) 次。
然后总复杂度就是 \(O(V^2+n)\)。

考虑一下具体实现。
反过来考虑,考虑一个点更新它的所有出边,因为优美的性质集中在目标点。
相当于我们可以预处理出 \((a,qwq)\) 可以更新到哪些点。
如果它已经被更新了那我们直接可以不管它了。
而且如果当前有一个 \((a,qwq)\) 和 \((a,qaq)\) 且 \(qwq\ge qaq\) 那 \((a,qaq)\) 是无意义的。
本质上来说我们可以把某个指定点的每一层给压起来。
然后只需要记录当前这个点的所有层可以转移到哪些点就行了。

Coding.

点击查看代码
//Coded by STUPID_JUSTlN {{{
//Gened on 2021.10.24 18:05:02
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
int n,a[1000005],go[5005][8195],cn[8195],rs[8195],rst;
char dp[8195][5005],v[5005][8195];//走权为 i 的边能到 j
inline void adde(int i,int j) {go[i][++cn[i]]=j;}
int main()
{
	read(n),dp[0][0]=1;for(int i=1;i<=5000;i++) adde(i,i),v[i][i]=1;
	for(int k;n-->0;)
	{
		read(k);
		for(int i=1;i<=cn[k];i++)
		{
			int tw=go[k][i];dp[tw][k]=1;
			for(int j=k+1;j<=5000;j++) if(v[j][tw^j]) break;
				else v[j][tw^j]=1,adde(j,tw^j);
		}cn[k]=0;
	}
	for(int i=0;i<8192;i++) for(int j=0;j<=5000;j++) if(dp[i][j]) {rs[++rst]=i;break;}
	printf("%d\n",rst);for(int i=1;i<=rst;i++) printf("%d%c",rs[i],i==rst?'\n':' ');
	return 0;
}

标签:le,XOR,8195,CF1582F,更新,read,int,Korney,qwq
来源: https://www.cnblogs.com/pealfrog/p/15456979.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有