LibreOJ2302 - 「NOI2017」整数
Description
有一个整数\(x=0\),对其进行\(n(n\leq10^6)\)次操作:
- 给出\(a(|a|\leq10^9),b(b\leq30n)\),将\(x\)加上\(a\cdot 2^b\)。
- 询问\(x\)在二进制下位权为\(2^k(k\leq30n)\)的位的值。
保证任意时刻\(x\geq0\)。
Solution
用线段树来模拟二进制下的加减运算。
线段树上的每个位置维护\(30\)位二进制数,即第一位维护\(2^0...2^{29}\),第二位维护\(2^{30}...2^{59}\),以此类推。考虑当我们将某位置上的值修改为\(a\)后应当怎么做:
- 若\(a\in[0,2^{30})\),则什么也不做。
- 若\(a\geq2^{30}\),则需要进位:将前面一段连续的\(2^{30}-1\)修改为\(0\),然后将这段\(2^{30}-1\)前面的一个数\(+1\)。
- 若\(a<0\),则需要退位:将前面一段连续的\(0\)修改为\(2^{30}-1\),然后将这段\(0\)前面的一个数\(-1\)。
那么我们需要区间修改,单点查询,并维护每个区间从低位到高位连续的\(0/2^{30}-1\)的长度。具体细节可以看代码。
时间复杂度\(O(nlogn)\)。
Code
//「NOI2017」整数
#include <cstdio>
#include <cstring>
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0,f=1; char ch=gc();
while(ch<'0'||'9'<ch) f=(ch^'-')?f:-1,ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int const N=4e6+10;
int const N0=30;
int n=1e6+100;
int Q,t1,t2,t3;
#define Ls (p<<1)
#define Rs ((p<<1)|1)
int rt,len[2][N],val[N],tag[N];
void update(int p,int L0,int R0)
{
int mid=L0+R0>>1;
len[0][p]=len[0][Ls]+(len[0][Ls]==mid-L0+1)*len[0][Rs];
len[1][p]=len[1][Ls]+(len[1][Ls]==mid-L0+1)*len[1][Rs];
}
void change(int p,int L0,int R0,int x)
{
if(x) val[p]=(1<<N0)-1; else val[p]=0;
tag[p]=x,len[x][p]=R0-L0+1,len[x^1][p]=0;
}
void pushdw(int p,int L0,int R0)
{
if(tag[p]<0) return;
int mid=L0+R0>>1;
change(Ls,L0,mid,tag[p]),change(Rs,mid+1,R0,tag[p]);
tag[p]=-1;
}
int L,R,cyV;
void ins1(int p,int L0,int R0,int v)
{
if(L<=L0&&R0<=R)
{
val[p]+=v;
if(val[p]>=(1<<N0)) cyV=1,val[p]&=(1<<N0)-1;
if(val[p]<0) cyV=0,val[p]+=1<<N0;
len[0][p]=len[1][p]=0;
if(val[p]==0) len[0][p]=1;
if(val[p]==(1<<N0)-1) len[1][p]=1;
return;
}
pushdw(p,L0,R0);
int mid=L0+R0>>1;
if(L<=mid) ins1(Ls,L0,mid,v);
if(mid<R) ins1(Rs,mid+1,R0,v);
update(p,L0,R0);
}
void ins2(int p,int L0,int R0,int v)
{
if(L<=L0&&R0<=R) {change(p,L0,R0,v); return;}
pushdw(p,L0,R0);
int mid=L0+R0>>1;
if(L<=mid) ins2(Ls,L0,mid,v);
if(mid<R) ins2(Rs,mid+1,R0,v);
update(p,L0,R0);
}
int query1(int p,int L0,int R0)
{
if(L<=L0&&R0<=R) return val[p];
pushdw(p,L0,R0);
int mid=L0+R0>>1;
if(L<=mid) return query1(Ls,L0,mid);
if(mid<R) return query1(Rs,mid+1,R0);
}
//query2返回在[L0,R0]∩[L,R]中L向后有多少个连续的v
int query2(int p,int L0,int R0,int v)
{
if(L<=L0&&R0<=R) return len[v][p];
pushdw(p,L0,R0);
int mid=L0+R0>>1,r1=0,r2=0;
if(L<=mid) r1=query2(Ls,L0,mid,v);
if(mid<R) r2=query2(Rs,mid+1,R0,v);
if(L<=mid) return r1+(r1==mid-L+1)*r2;
else return r2;
}
void add(int x,int v)
{
L=R=x,cyV=-1; ins1(rt,1,n,v);
if(cyV>=0)
{
L=x+1,R=n; int len=query2(rt,1,n,cyV);
L=x+1,R=x+len; if(L<=R) ins2(rt,1,n,cyV^1);
L=R=x+len+1; ins1(rt,1,n,cyV?1:-1);
}
}
int main()
{
Q=read(); t1=read(),t2=read(),t3=read();
memset(tag,-1,sizeof tag);
rt=1;
change(rt,1,n,0);
for(int i=1;i<=Q;i++)
{
int opt=read();
if(opt==1)
{
int a=read(),b=read();
int b1=b/N0+1,b2=b%N0,t=1<<(N0-b2);
int a1=a/t,a2=a%t*(1<<b2);
add(b1,a2); add(b1+1,a1);
}
else
{
int k=read();
int k1=k/N0+1,k2=k%N0;
L=R=k1; printf("%d\n",(query1(rt,1,n)>>k2)&1);
}
}
return 0;
}
P.S.
多谢Pickupwin大佬指点
LibreOJ2302 - 「NOI2017」整数的更多相关文章
- 「NOI2017」整数 解题报告
「NOI2017」整数 有一些比较简单的\(\log^2n\)做法 比如暴力在动态开点线段树上维护每个位置为\(0\)还是\(1\),我们发现涉及到某一位加上\(1\)或者减去\(1\)实际上对其他位 ...
- LOJ2302 「NOI2017」整数
「NOI2017」整数 题目背景 在人类智慧的山巅,有着一台字长为$1048576$位(此数字与解题无关)的超级计算机,著名理论计算机科 学家P博士正用它进行各种研究.不幸的是,这天台风切断了电力系统 ...
- LOJ#2302. 「NOI2017」整数
$n \leq 1000000$个操作:一,给$x$加上$a*2^b$:二,问$x$的某个二进制位$k$.$b,k \leq 30n$,$|a| \leq 1e9$. 30暴露了一切..可以把30个二 ...
- LOJ 2302 「NOI2017」整数——压位线段树
题目:https://loj.ac/problem/2302 压30位,a最多落在两个位置上,拆成两次操作. 该位置加了 a 之后,如果要进位或者借位,查询一下连续一段 0 / 1 ,修改掉,再在含有 ...
- loj #2305. 「NOI2017」游戏
#2305. 「NOI2017」游戏 题目描述 小 L 计划进行 nnn 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 AAA.BBB. ...
- LOJ2305 「NOI2017」游戏
「NOI2017」游戏 题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行$n$场 ...
- LOJ2303 「NOI2017」蚯蚓排队
「NOI2017」蚯蚓排队 题目描述 蚯蚓幼儿园有$n$只蚯蚓.幼儿园园长神刀手为了管理方便,时常让这些蚯蚓们列队表演. 所有蚯蚓用从$1$到$n$的连续正整数编号.每只蚯蚓的长度可以用一个正整数表示 ...
- LOJ_2305_「NOI2017」游戏 _2-sat
LOJ_2305_「NOI2017」游戏 _2-sat 题意: 给你一个长度为n的字符串S,其中第i个字符为a表示第i个地图只能用B,C两种赛车,为b表示第i个地图只能用A,C两种赛车,为c表示第i个 ...
- 「NOI2017」游戏
「NOI2017」游戏 题目描述 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 \(A\).\(B\).\ ...
随机推荐
- P3742 umi的函数
题目背景 umi 找到了一个神秘的函数 f. 题目描述 这个函数接受两个字符串 s1,s2.这些字符串只能由小写字母组成,并且具有相同的长度.这个函数的输出是另一个长度与 s1,s2 相同的字符串 g ...
- re正则表达式公式讲解5
1.refullmatch() 完全匹配字符串则返回object,否则返回None import re s = "max@123uyt146" print(re.fullmatch ...
- Java&Xml教程(十)XML作为属性文件使用
我们通常会将Java应用的配置参数保存在属性文件中,Java应用的属性文件可以是一个正常的基于key-value对,以properties为扩展名的文件,也可以是XML文件. 在本案例中,將会向大家介 ...
- postgresql版sde(10.4.1)新建数据库
使用sde pg版,第一次建sde库就是新安装sde的方法 然而从第二次开始可以有其他方式 新建一般的pg数据再转为sde数据库: 首先用建一般的pg数据库 首先要新建数据库 数据库名:新建的数据库名 ...
- ubuntu下php安装目录说明
php当前安装目录 /etc/php5/ apache2: 采用APACHE2HANDLER启动 cli: 采用命令启动 fpm php-fpm启动 fpm2 php-fpm多实例 m ...
- 生产线上的Nginx如何添加未编译安装模块
正在生产线上跑着web前端是nginx+tomcat,现在有这样一个需求,需要对网站的单品页面和列表页设置缓存,不同的页面设置不同的缓存,但是由于开始没有安装ngx_cache_purge这个模块,现 ...
- [Windows Server 2012] 安装IIS8.5及FTP
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:安装IIS ...
- vSphere Client用户名密码保存记录
vSphere Client在访问ESXi主机或vCenter后是默认不保存登录用户名和密码的,不过可以通过修改配置文件来保存,方便访问连接. 方法如下: 打开配置文件路径(实际安装路径):D:\Pr ...
- JAVA自定义栈
public class Stack{ int[] data; int maxSize; int top; public Stack(int maxSize) { this.maxSize=maxSi ...
- C++静态全局变量和全局变量的区别
静态全局变量 非静态全局变量 存储方式 静态存储 静态存储 作用域 定义该变量的源文件内 所有源文件 解释: 共同点:全局变量(外部变量)的说明之前再冠以static 就构 成了静态的全局变量.全 ...