[NOI2017]整数
https://www.luogu.org/problemnew/show/P3822
题解
如果只有加法没有减法,那么我们朴素进位的时间复杂度是均摊\(O(1)\)的。
那么减法的话我们维护一个增量的数,一个减量的数,就是一个存所有\(a>0\)的变量,一个存所有\(a<0\)的变量。
那么我们考虑一个位置的数是\(0\)还是\(1\),我们先对这个位置做个减法,然后唯一对这个值有影响的就是低位是否有借位,如果有,这一位就翻转。
那么问题就转化为比较两个数的大小,用set维护不一样的位置就行了。
然后这道题的范围是\(30n\),所以我们可以把每\(30\)个位压成一个\(int\)存就可以了,每次只会对两个位置进行修改。
注意,提取一个负数的某个二进制位的时候可能会出问题,最好把它搞成正的再去做。
代码
#include <bits/stdc++.h>
#define N 1000002
using namespace std;
typedef long long ll;
typedef unsigned int u;
int maxn=1000000;
int n,t1,t2,t3;
u z[N],f[N];
bool cun[N];
set<int>s;
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
inline void work(int x){
if(z[x]==f[x]){
s.erase(x);
}
else s.insert(x);
}
int main(){
n=rd();
t1=rd();t2=rd();t3=rd();
int opt;
int a,b;////
u maxx=(1u<<30)-1;
while(n--){
opt=rd();
if(opt==1){
a=rd();b=rd();
int wei=maxn-int(b/30);
int _wei=b%30;
int tg=0;
if(a<0)tg=1,a=-a;/////
for(int j=0;j<30;++j){
cun[j]=(a&(1u<<j))!=0;
}
if(tg)a=-a;
int now=30-_wei;//
u num=0;
for(int j=0;j<now;++j){
num+=(1u<<j)*cun[j];
}
if(a>0){
num<<=_wei;
z[wei]=(num+z[wei]);
num=0;
if(z[wei]>maxx)
z[wei]=z[wei]&maxx,num=1;
for(int j=now;j<30;++j){
num+=cun[j]*(1u<<j-now);
}
--wei;
z[wei]+=num;
while(wei>0&&z[wei]>maxx){
z[wei]&=maxx;
z[wei-1]++;
wei--;
}
}
else{
num<<=_wei;
f[wei]=(num+f[wei]);
num=0;
if(f[wei]>maxx)
f[wei]=f[wei]&maxx,num=1;
for(int j=now;j<30;++j){
num+=cun[j]*(1u<<j-now);
}
--wei;
f[wei]+=num;
while(wei>0&&f[wei]>maxx){
f[wei]&=maxx;
f[wei-1]++;
wei--;
}
}
int chu=maxn-int(b/30);
for(int j=wei;j<=chu;++j)work(j);
}
else{
b=rd();
int wei=maxn-int(b/30);
int _wei=b%30;
int ans=(((z[wei]&(1<<_wei))!=0)-((f[wei]&(1<<_wei))!=0)+2)%2;
bool tag=0;
for(int j=_wei-1;j>=0;--j)
if((z[wei]&(1<<j))!=(f[wei]&(1<<j))){
tag=1;
if((z[wei]&(1<<j))<(f[wei]&(1<<j)))ans^=1;
break;
}
if(!tag){
set<int>::iterator it=s.upper_bound(wei);
if(it!=s.end()){
int x=*it;
for(int j=29;j>=0;--j){
if((z[x]&(1<<j))!=(f[x]&(1<<j))){
tag=1;
if((z[x]&(1<<j))<(f[x]&(1<<j)))ans^=1;
break;
}
}
}
}
printf("%d\n",ans);
}
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· 程序员转型AI:行业分析
· 深入集成:使用 DeepSeek SDK for .NET 实现自然语言处理功能
· 为DeepSeek添加本地知识库
· .NET程序员AI开发基座:Microsoft.Extensions.AI