CF939 D
- 让你把区间分成 段, 段内用 连接, 段之间用 连接,问你在结果不大于 的前提下, 的最大值
- 标签:正向思维,二进制操作,按位贪心(从高到低)
- 参考题解1,参考题解2
- 注释版code
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
using namespace std;
using ll=long long;
const int N=1e5+5;
int t,n,x,ans=-1;
inline void sol(vector<int> a,const int p=30){
if(p<0) return ans=max(ans,(int)a.size()),void();
vector<int> pos;
F(i,0,(int)a.size()-1){
if((a[i]>>p)&1) pos.emplace_back(i);
}
if(pos.size()%2==1 && ((x>>p)&1)==0) return;
if(pos.size()%2==1 && ((x>>p)&1)==1) return sol(a,p-1);
bool rmv[(int)a.size()];
vector<int> b,c=a;
memset(rmv,0,sizeof(rmv));
for(int i=0;i<(int)pos.size();i+=2){
for(int j=pos[i]+1;j<=pos[i+1];++j){
rmv[j]=1; c[pos[i]]^=c[j];
}
}
F(i,0,(int)a.size()-1){
if(!rmv[i]) b.emplace_back(c[i]);
}
if(((x>>p)&1)==0) return sol(b,p-1);
ans=max(ans,(int)b.size());
return sol(a,p-1);
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>t; while(t--){
cin>>n>>x;
vector<int> a(n);
F(i,0,n-1) cin>>a[i];
ans=-1;
sol(a);
cout<<ans<<'\n';
}
return 0;
}
- 反思:
- 经典的二进制贪心,从低位到高位。核心在以贪心的方式把 运算给回避掉了,这样就这剩下一种运算需要处理。
- 另一方面就是直白的正向思维(感觉有点儿反套路化逆向思维的感觉),就逐渐逐渐加符号上去,而不是先全填成 或者 再去改。想多了的话反而容易遭。
- 二进制贪心不一定是什么一个前缀相同然后0,1之间讨论大小关系, 但共同点是两种贪心都和势能很像:只关注已有的条件来推测最终的结果,中间具体状态不关心。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】