Codeforces Round #830 (Div. 2) 题解
AB 太简单了,不写解法了。
CF1732C Sheikh
我们观察一下 的性质。
考虑假如一个数 ,对 的贡献为 ,而对 的贡献小于等于 ,因为可能异或和中已经有位为 。
所以固定 , 单调递增,固定 也有此性质。
另一个显而易见的结论是假如不要求区间长度最小, 就是最终的答案,所以其实最大值已经确定为 ,只需要找长度最小的区间满足 即可。
由此结论,我们可以完成 C1,对于 ,先判断如果 取 也就是最大能不能达到 ,若能二分出使 最大的 ,最后求出最小长度即可。
复杂度 ,其中 .
接下来考虑 C2, 和 同阶,所以我们一次询问要求做到 以内。
不知道有多少人可能想到过一个错误的做法:初始区间为 ,若左右端点能缩就缩。
我们规定 , 为 作为右端点时区间满足 左端点的最大值。
它错的原因是没有考虑每一个 所对应的最小 ,而是直接考虑了最大的 对应的最小 ,从而遗漏了一些情况。
那么假如我们枚举每一个 ,然后二分的话,复杂度如何呢?
显然如果区间中 很多,一次询问就会被卡到 ,这是我们不能接受的。
如果排除 的干扰,考虑答案区间 ,它满足加入 或 后值不变(前提时 ),说明 或 的二进制位在 中都为 ,那么最多有多少个这样的数呢,我们考虑每一个未加入的数都是 ,约有 个。所以 是小于 的,复杂度就有了保证。
加上 的干扰,我们只需要预处理出每一个数前面和后面第一个非 数,然后枚举 改成 从 及之后第一个非 数开始往后跳 次即可。
复杂度 ,但显然跑不满。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c<='9'&&c>='0'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
void print(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
const int N=1e5+5;
int T,n,q,a[N],sum[N],xsum[N];
int erfen1(int ll,int rr,int fmax){
int l=ll,r=rr,mid;
while(l<r){
mid=l+r>>1;
if(sum[mid]-sum[ll-1]-(xsum[mid]^xsum[ll-1])>=fmax)r=mid;
else l=mid+1;
}
return l;
}
int erfen2(int ll,int rr,int fmax){
int l=ll,r=rr,mid;
while(l<r){
mid=l+r+1>>1;
if(sum[rr]-sum[mid-1]-(xsum[rr]^xsum[mid-1])>=fmax)l=mid;
else r=mid-1;
}
return l;
}
int nxt[N],pre[N];
signed main(){
T=read();
while(T--){
n=read(),q=read();
for(int i=1;i<=n;++i){
a[i]=read();
sum[i]=sum[i-1]+a[i];
xsum[i]=(xsum[i-1]^a[i]);
}
int lst=0;
for(int i=1;i<=n;++i){
pre[i]=lst;
if(!a[i])continue;
lst=i;
}
lst=n+1;
for(int i=n;i>=1;--i){
nxt[i]=lst;
if(!a[i])continue;
lst=i;
}
while(q--){
int L=read(),R=read();
if(sum[R]==sum[L-1]){print(L),printf(" "),print(L),puts("");continue;}
if(!a[L])L=nxt[L];
if(!a[R])R=pre[R];
int fmax=sum[R]-sum[L-1]-(xsum[R]^xsum[L-1]);
int cnt=erfen2(L,R,fmax)-L+1,l=L,r=R,i=L;
while(cnt--){
if(sum[R]-sum[i-1]-(xsum[R]^xsum[i-1])<fmax)break;
int j=erfen1(i,R,fmax);
if(j-i<r-l)l=i,r=j;
i=nxt[i];
if(i>n)break;
}
print(l),printf(" "),print(r),puts("");
}
}
return 0;
}
CF1732D
暴力与优化结合,从而获得较优的复杂度。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c<='9'&&c>='0'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
void print(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
int q;
set<int>s1,s2;
map<int,int>f;
signed main(){
q=read();
s1.insert(0);
while(q--){
char opt;
cin>>opt;
int x=read();
if(opt=='+'){
s1.insert(x),f[x]=x+x;
if(s2.count(x))s2.erase(x);
}else if(opt=='-'){
s2.insert(x);
if(s1.count(x))s1.erase(x);
}else{
int tmp;
if(f[x])tmp=f[x];
else tmp=x;
while(s1.count(tmp))tmp+=x;
f[x]=tmp;
for(auto i=s2.lower_bound(x);i!=s2.end();++i){
if((*i)>tmp)break;
if((*i)%x==0){
tmp=(*i);break;
}
}
print(tmp),puts("");
}
}
return 0;
}
E 赛时都没做到,不想花时间补了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)