NOI模拟 排序幻觉
1.NOIP模拟 排序2.NFLS 231031 比赛总结3.JOI2013Final/LOJ2763 现代豪宅4.省选模拟 序列5.省选模拟 过路费6.NOI模拟 序列7.NOI模拟 大战波特8.NOI模拟 Mizuki 与进化9.NOI模拟 刀客球10.NOI模拟 真夏は誰のモノ11.NOI模拟 树数术12.NOI模拟 序列13.NOI模拟 GCD14.NOI模拟 开关
15.NOI模拟 排序幻觉
16.NOI模拟 UTF-817.NOI模拟 捉迷藏18.退背包简介/NOI模拟 卖画19.CSP模拟 取模20.CSP模拟 矩阵操作21.AGC007F Shik and Copying String22.洛谷P10336 [UESTCPC 2024] 2-聚类算法23.NFLS 241014 比赛总结24.QOJ5173 染色25.洛谷P11183 [ROIR 2018 Day2] 大数据处理涉及知识点:二进制,贪心
题意
给一个数组 ,选择一个数 ,如果 满足:
则称 是数组 的幻数。
有 次询问,每次永久修改一个数。对于原数组与每次询问后输出最小的幻数,不存在幻数输出 。
。
思路
对于这种按位异或的题目,可以去尝试每位单独考虑。
对于 ,称它们二进制下从左往右第一个不同的位为第 位(以下“位”均指二进制下)。
- 时,我们同时将 第 位左边的位取反不会影响它们的大小关系,因为第 位左边它们两都一样,取反不会影响大小关系;而如果将第 位右边的位取反也没用,因为第 位已经不一样了,判断大小时是从高位到低位比的。所以只能把第 位取反才能反转它们的大小关系。
- 时,无论同时取反哪一位, 都永远等于 。
- 时,同理取反第 位左边或右边的位都不会影响它们之间的大小关系,唯有取反第 位会反转它们的大小关系。
因此我们对于所有 求出它们的 ,如果 那么第 位不能取反,如果 那么第 位必须取反,如果有冲突说明无解,否则,必须取反的位为 ,其余位为 的二进制数便是最小的幻数。
如何处理修改呢?一个数的贡献只与旁边的两个数有关,分开记录“必须取反”与“不能取反”,一个数的做出贡献在第 处 +1
,撤销时在第 处 -1
,每次只需要 就可以扫描是否有冲突并求出答案,具体看代码。
代码
#include<bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar __getchar
inline char __getchar(){
static char ch[1<<20],*l,*r;
return (l==r&&(r=(l=ch)+fread(ch,1,1<<20,stdin),l==r))?EOF:*l++;
}
#endif
template<class T>inline void rd(T &x){
T res=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
static char wtbuff[20];
static int wtptr;
if(x==0){
putchar('0');
}
else{
if(x<0){x=-x;putchar('-');}
wtptr=0;
while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
while(wtptr--) putchar(wtbuff[wtptr]);
}
if(endch!='\0') putchar(endch);
}
typedef long long LL;
const int MAXN=1e6+5,MAXB=32;
int n,q;
LL a[MAXN];
int forbid[MAXB],active[MAXB];
inline int find_first_diff(LL x,LL y){
int res=-1;
LL cmp=1;
for(int i=0;i<=30;i++,cmp<<=1){
if((x&cmp)!=(y&cmp)) res=i;
}
return res;
}
inline void check(){
for(int i=0;i<=30;i++){
if(active[i] && forbid[i]){
puts("-1");
return;
}
}
LL res=0,cmp=1;
for(int i=0;i<=30;i++,cmp<<=1){
if(active[i]) res+=cmp;
}
wt(res,'\n');
}
int main(){
rd(n);
for(int i=1;i<=n;i++){
rd(a[i]);
}
for(int i=2;i<=n;i++){
if(a[i]>a[i-1]) forbid[find_first_diff(a[i],a[i-1])]++;
else if(a[i]<a[i-1]) active[find_first_diff(a[i],a[i-1])]++;
}
check();
rd(q);
for(int i=1,p;i<=q;i++){
LL v;
rd(p);rd(v);
if(p!=1){
if(a[p]>a[p-1]) forbid[find_first_diff(a[p],a[p-1])]--;
else if(a[p]<a[p-1]) active[find_first_diff(a[p],a[p-1])]--;
}
if(p!=n){
if(a[p+1]>a[p]) forbid[find_first_diff(a[p+1],a[p])]--;
else if(a[p+1]<a[p]) active[find_first_diff(a[p+1],a[p])]--;
}
a[p]=v;
if(p!=1){
if(a[p]>a[p-1]) forbid[find_first_diff(a[p],a[p-1])]++;
else if(a[p]<a[p-1]) active[find_first_diff(a[p],a[p-1])]++;
}
if(p!=n){
if(a[p+1]>a[p]) forbid[find_first_diff(a[p+1],a[p])]++;
else if(a[p+1]<a[p]) active[find_first_diff(a[p+1],a[p])]++;
}
check();
}
return 0;
}
本文作者:MessageBoxA
本文链接:https://www.cnblogs.com/SkyNet-PKN/p/18216009
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步