• CF1582F Korney Korneevich and XOR


    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;
    }
    
  • 相关阅读:
    swift中的"类型擦除"
    Swift Pointer 使用指南
    Swift Method Dispatching — a summary of my talk at Swift Warsaw
    Swift库二进制接口(ABI)兼容性研究
    编译器最重要的工作就是确定对象内存模型
    Objective-C类成员变量深度剖析--oc对象内存模型
    Swift进阶之内存模型和方法调度
    Swift 对象内存模型探究(一)
    编程领域中的 "transparent" 和 "opaque"
    structure vs class in swift language
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15456979.html
Copyright © 2020-2023  润新知