官方题解
- 题意:给数列a[],选择尽量多的数满足任意两个异或起来<=k
1625D - Binary Spiders
- 思路:首先,将数列排序得到,然后升序取得的值的任意两个最小值为相邻两个异或的最小值。
证明:zxcv告诉我可以考虑在trie树上,dfs序等价于字典序,然后一个树与其lca最深(异或值最小)的叶子节点必是dfs序(字典序)最接近的,即相邻的,得证。
这个结论非常有用!我们就可dp了。dp[i]=dp[j]+1满足ai xor aj>=k
有了O(n2)的,然后用上01trie树优化找与ai异或值<=k。只需要O(30n)
具体的(其实很好想:)
k表示当前位K的值
k=0:只能找异或起来等于0的走
k=1:走异或为1的,然后用为0的子树更新dp[i](这里我们要在trie树上维护子树的dp最大值)
总之我们走的路径都表示该结果与k的前dep位相等。
- code:
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int go[N*31][2],mx[N*31],pre[N],dp[N],n,k,ncnt;
struct node {int val,id;}a[N];
bool cmp(node u,node v) {return u.val<v.val;}
void Insert(int u,int d,int x) {
if(d<0) {mx[u]=x;return;}
bool w=(a[x].val>>d)&1;
if(!go[u][w]) go[u][w]=++ncnt;
Insert(go[u][w],d-1,x);
if(go[u][w^1])mx[u]=(dp[mx[go[u][0]]]>dp[mx[go[u][1]]])?mx[go[u][0]]:mx[go[u][1]];
else mx[u]=mx[go[u][w]];
}
int Fd(int x) {
int u=0,res=0;
for(int i=29;i>=0;i--) {
bool w=x&(1<<i),p=k&(1<<i);
if(p) {if(go[u][w^1])u=go[u][w^1];else return res;}
else {
int t1=go[u][w^1];if(t1&&dp[mx[t1]]>dp[res])res=mx[t1];
if(go[u][w])u=go[u][w];else return res;
}
}
if(dp[res]<dp[mx[u]]) res=mx[u];
return res;
}
int main() {
int ans=0,pos;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i].val),a[i].id=i;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++) {
pre[i]=Fd(a[i].val);dp[i]=dp[pre[i]]+1;
Insert(0,29,i);
if(dp[i]>ans)ans=dp[i],pos=i;
}
if(ans==1) printf("-1");
else {
printf("%d\n",ans);
for(int t=pos;t;t=pre[t]) printf("%d ",a[t].id);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人