[NOI2017] 整数
XL.[NOI2017] 整数
首先可以想到一种用线段树维护每一位的方法:一个数 拆成 个位置上 ,执行单点 的时候如果出现进位就找到右方第一个非 的位置,然后单点加,区间赋 ;执行减法的时候,就是找到右方第一个非 的位置,单点减,然后区间赋 。(总之就是手工高精度竖式计算之类的)
但是这样复杂度就是 ,对于 不可能过。
然后,既然是高精度算法,那就可以压位,每 位压一块,这样执行一次加减法都不会爆 int
。加法时就找到右方第一个非满的位置,减法时就找到右方第一个非零的位置,都可以线段树上二分简单维护。
时间复杂度 。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int LG=30;
const int MD=1<<30;
int n;
#define lson x<<1
#define rson x<<1|1
#define mid ((l+r)>>1)
struct SegTree{
int nz,nf,tag;//none-zero position,none-full position
SegTree(){nz=nf=tag=-1;}
}seg[5001000];
#define LSON lson,l,mid
#define RSON rson,mid+1,r
#define X x,l,r
void MOD(int x,int l,int r,int y){if(!y)seg[x].nf=l,seg[x].nz=-1;if(y==MD-1)seg[x].nz=l,seg[x].nf=-1;seg[x].tag=y;}
void pushdown(int x,int l,int r){if(seg[x].tag!=-1)MOD(LSON,seg[x].tag),MOD(RSON,seg[x].tag),seg[x].tag=-1;}
void pushup(int x){if(seg[lson].nf!=-1)seg[x].nf=seg[lson].nf;else seg[x].nf=seg[rson].nf;if(seg[lson].nz!=-1)seg[x].nz=seg[lson].nz;else seg[x].nz=seg[rson].nz;}
void upd(int x,int l,int r){if(seg[x].tag)seg[x].nz=l;else seg[x].nz=-1;if(seg[x].tag!=MD-1)seg[x].nf=l;else seg[x].nf=-1;}
bool ADD(int x,int l,int r,int P,int y){
if(l>P||r<P)return false;
if(l==r){seg[x].tag+=y;bool ret=false;if(seg[x].tag>=MD)seg[x].tag-=MD,ret=true;upd(X);return ret;}
pushdown(X);bool ret=ADD(LSON,P,y)||ADD(RSON,P,y);pushup(x);return ret;
}
bool SUB(int x,int l,int r,int P,int y){
if(l>P||r<P)return false;
if(l==r){seg[x].tag-=y;bool ret=false;if(seg[x].tag<0)seg[x].tag+=MD,ret=true;upd(X);return ret;}
pushdown(X);bool ret=SUB(LSON,P,y)||SUB(RSON,P,y);pushup(x);return ret;
}
bool ADD1(int x,int l,int r,int P){
if(r<=P)return false;
if(l>P&&seg[x].nf==-1){MOD(X,0);return false;}
if(l==r){seg[x].tag++,upd(X);return true;}
pushdown(X);bool ret=ADD1(LSON,P)||ADD1(RSON,P);pushup(x);return ret;
}
bool SUB1(int x,int l,int r,int P){
if(r<=P)return false;
if(l>P&&seg[x].nz==-1){MOD(X,MD-1);return false;}
if(l==r){seg[x].tag--,upd(X);return true;}
pushdown(X);bool ret=SUB1(LSON,P)||SUB1(RSON,P);pushup(x);return ret;
}
void build(int x,int l,int r){if(l==r)seg[x].tag=0,seg[x].nf=l;else build(LSON),build(RSON),pushup(x);}
bool query(int x,int l,int r,int P,int k){if(l>P||r<P)return false;if(l==r)return (seg[x].tag>>k)&1;pushdown(X);return query(LSON,P,k)||query(RSON,P,k);}
void ADD(int a,int p){if(ADD(1,0,n+10,p,a))ADD1(1,0,n+10,p);}
void SUB(int a,int p){if(SUB(1,0,n+10,p,a))SUB1(1,0,n+10,p);}
void modify(int a,int b){
if(!a)return;
bool sub=false;if(a<0)a=-a,sub=true;
int p=b/LG;b%=LG;
ll A=((ll)a)<<b;
// printf("%lld %d %d\n",A,p,b);
if(!sub){ADD(A%MD,p);if(A>=MD)ADD(A/MD,p+1);}
else{SUB(A%MD,p);if(A>=MD)SUB(A/MD,p+1);}
}
bool query(int p){return query(1,0,n+10,p/LG,p%LG);}
int read(){
int x=0,fl=1;char c=getchar();
for(;c>'9'||c<'0';c=getchar())if(c=='-')fl=-fl;
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return fl==1?x:-x;
}
void iterate(int x,int l,int r){if(l==r)printf("%d ",seg[x].tag);else pushdown(X),iterate(LSON),iterate(RSON);}
int main(){
// freopen("integer3.in","r",stdin);
n=read(),read(),read(),read();
build(1,0,n+10);
// iterate(1,0,n+10),puts("");
for(int i=1,tp,a,b;i<=n;i++){
tp=read(),a=read();
if(tp==1)b=read(),modify(a,b);
else printf("%d\n",query(a));
// iterate(1,0,n+10),puts("");
}
return 0;
}
分类:
数据结构
, 数据结构——树状数组/线段树/ST表
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?