1 条题解
-
0
自动搬运
来自洛谷,原作者为

XY_cpp
**搬运于
2025-08-24 21:47:24,当前版本为作者最后更新于2019-08-03 11:22:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这题调了一个上午不知哪里错了,
可能我写代码像c*k十年生死两茫茫,BUG何处藏,唯有泪千行
于是乎,随便打了个暴力碰运气,吸一口氧气,还不够,再吸一口臭氧
// luogu-judger-enable-o2 #pragma GCC optimize("O3") #include<bits/stdc++.h> using namespace std; const int N=2e5+1; int a[N],b[N],x[N],l[N],r[N]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=m;++i) scanf("%d%d%d%d",&b[i],&x[i],&l[i],&r[i]); for(int i=1;i<=m;++i) { int res=0; for(int j=l[i];j<=r[i];++j) { int now=b[i]^(a[j]+x[i]); res=max(res,now); } printf("%d\n",res); } return 0; }正所谓
n方过百万,暴力碾标算
不过如果你像我一样,是个求知若渴,勤奋好学的好孩子,请看下面的正解
我来口胡一下正解
睡了一个中午醒来看了一眼题面,发现可以是,于是恍然大悟
大雾,把左边端点改成,宝宝就愉快的了题目要求 显然不能硬求,看到异或,考虑按照位处理
假设从高到低处理到第位(从右往左数,个位是第位),
设之前求出的的答案为(如果你不太明白这个变量的意思,请看下面的例子,前提是你要知道基本的性质)
当前处理到第位
所以当前记录的是一个满足题目限制的,使得 的位达到最大值,我们之所以要从高到低枚举,就是因为要贪心的求,先让高位满足最大值.
这时,聪明的你就要发问了:万一没有一个能使某一位达到最大值,那怎么办呢?
答:没有办法, 之后的这一位只能为
经过一番分析之后,我们得出核心思路:
若第 的第位是,那么我们希望它是长这样的
$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ b:---1**\ * $$容易求出
同理当的第位是时
我们可以直接主席树上查询对于第个人的内有无满足上述条件
- 当的第位是时,若有这样一个,,反之
- 当的第位是时,若有这样一个,,反之
关于主席树部分,因为有区间内查询的约束,所以我们首先想到的是主席树
首先按照套路把,提出来,相减后得出这段区间内的数值个数,然后按照一般套路分成两半往下找就可以了
如果你连主席树部分都不能理解,建议先把模版切熟练
上代码,很短,
暴力更短#include<bits/stdc++.h> using namespace std; const int N=5e5+5; int a[N],rt,t[N<<5],ch[N<<5][2],sum[N<<5]; void update(int pre,int &k,int l,int r,int x) { if(r<x||l>x) return ; k=++rt,ch[k][0]=ch[pre][0],ch[k][1]=ch[pre][1],sum[k]=sum[pre]+1; if(l==r) return; int mid=(l+r)>>1; update(ch[pre][0],ch[k][0],l,mid,x); update(ch[pre][1],ch[k][1],mid+1,r,x); } int query(int u,int v,int l,int r,int x,int y) { int num=sum[v]-sum[u],mid=(l+r)>>1; if(y<l||x>r||num==0) return 0; if(x<=l&&r<=y) return num; return query(ch[u][0],ch[v][0],l,mid,x,y)+query(ch[u][1],ch[v][1],mid+1,r,x,y); } int main() { int n,m,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]),m=max(a[i],m); for(int i=1;i<=n;i++) update(t[i-1],t[i],0,m,a[i]); while(q--) { int b,x,l,r,ans=0; scanf("%d%d%d%d",&b,&x,&l,&r); for(int i=18;i>=0;i--) { if(b&(1<<i)&&!query(t[l-1],t[r],0,m,ans-x,ans-x+(1<<i)-1)) ans+=(1<<i);//之前就是这写错了 if(!(b&(1<<i))&&query(t[l-1],t[r],0,m,ans-x+(1<<i),ans-x+(1<<(i+1))-1)) ans+=(1<<i); } printf("%d\n",ans^b); } return 0; }
- 1
信息
- ID
- 2366
- 时间
- 3000ms
- 内存
- 252MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者