再解 [NOI2017] 整数
提供一个来自 CF 大佬 adament 的有趣思路。
首先我们知道的是一个只增加的 进制整数计数器,如果 是常数那么复杂度是均摊 的。证明只需要考虑将 进制中为 的所有位的位数当成势能,那么每一次进位一定是 一定会消耗势能函数。
但这道题有加又有减,问题出在了可能有“退位” ,这时导致了势能函数的增加,这也是为什么均摊算法通常不能支持撤回。常规的做法是把加减分开考虑变成只加的情况。其实还有一种更简单的做法:我们不限制一个位上的值一定是 的,而是 。此时的进位/退位的形式都是 或 。我们将非零位的个数当成势能,这样进位/退位都会减小势能,而势能函数的总量就是 的了。
然而现在要查询原数某一位,如何来还原原数的一位呢?我们发现进位对于下一位的影响总是 的,我们只需要找到我们当前查询的位的严格非零前驱,判断一下它是否为负,如果是当前位就需要 然后输出。
具体到这题,我们需要将数 个压成一位,我实现压了 位。维护动态前驱用了 zkw 线段树上 finger search(只是减小常数)。输出时有个小技巧,负数的补码实际上就是它在二进制下的表示,所以提取负数的某一维可以直接跟正数一起位运算就可以了。
代码非常好写,跑得也飞快,复杂度 。
#include <cstdio> #include <bitset> using namespace std; int read(){ char c=getchar();int x=0;bool f=0; while(c<48||c>57) f|=(c=='-'),c=getchar(); do x=(x<<1)+(x<<3)+(c^48),c=getchar(); while(c>=48&&c<=57); if(f) return -x; return x; } const int lT=62,sT=30; typedef long long ll; const ll Base=(1ll<<lT); int q,dlt; namespace ds{ bitset<1<<20> f; void ins(int x){ x+=dlt; while(!f[x]) f[x]=1,x>>=1; } void del(int x){ x+=dlt; while(f[x]){ f[x]=0; if(f[x^1]) return; x>>=1; } } int pre(int x){ if(!x) return -1; x+=dlt-1; if(f[x]) return x-dlt; while(x>1){ if((x&1)&&f[x^1]) break; x>>=1; } x^=1; if(!x) return -1; while(x<dlt){x<<=1;if(f[x^1]) x^=1;} return x-dlt; } } ll a[500003]; void upd(int x,ll v){ if(!v) return; if(!a[x]) ds::ins(x); a[x]+=v; if(!a[x]) ds::del(x); } void inc(int x,int t){ bool sig=0; if(x<0) sig=1,x=-x; int bl=t/lT,wid=lT*(bl+1)-t; if(wid>sT) wid=sT; if(sig){ upd(bl,-((ll)(x&((1ll<<wid)-1))<<(t-bl*lT))); upd(bl+1,-(x>>wid)); } else{ upd(bl,(ll)(x&((1ll<<wid)-1))<<(t-bl*lT)); upd(bl+1,(x>>wid)); } ll tmp=0; int fl=0; do{ upd(bl,tmp); tmp=a[bl]/Base; upd(bl,-Base*tmp); ++bl;++fl; }while(fl<2||tmp); } bool qry(int x){ int bl=x/lT,p=ds::pre(bl);x%=lT; if(p>=0&&a[p]<0) return (a[bl]-1)>>x&1; else return a[bl]>>x&1; } int main(){ q=read();read();read();read(); for(dlt=1;dlt<=(q>>1)+1;dlt<<=1); while(q--){ int op=read(),x=read(); if(op==1) inc(x,read()); else printf("%d\n",qry(x)); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!