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\).\ ...
随机推荐
- 用私有构造器或者枚举类型强化Singleton
参考Effective Java第三版 Joshua J. Bloch 参与编写JDK的大佬,上次看Collections的源码时看见了他的名字,然后翻了翻书,竟然就是他写的! 1.常见的一种: pu ...
- 使用预定义的action值启动系统应用
1.启动浏览器 Intent intent = new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); //可以传一个搜索关键字,会直接显示 ...
- P1309 瑞士轮 未完成 60
题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分 ...
- mysql5.5版本导入sql报错
1 在5.5的版本中不支持utf8_german2的类型 2 在5.5版本中只支持timestamp类型设置默认值为CURRENT_TIMESTAMP,不支持datetime类型默认值设置为CURRE ...
- IOS之pageControl
用户点击页面控件,会触发UIControlEventValueChanged事件,并启动设置为控件动作的任何方法.可以通过调用currentPage查询控件的新值,并通过调整numberOfPages ...
- ZooKeeper读书笔记
<ZooKeeper读书笔记> 1.Zookeeper是什么?Zookeeper是一个典型的分布式数据一致性的解决方案,分布式应用可以基于它实现诸如数据发布/订阅.负载均衡.命名服务.分布 ...
- Android(java)学习笔记181:多媒体之图片画画板案例
1.首先我们编写布局文件activity_main.xml如下: <RelativeLayout xmlns:android="http://schemas.android.com/a ...
- Web框架_MVC vs MVT
MVC 大部分开发语言中都有MVC框架 MVC框架的核心思想是:解耦 降低各功能模块之间的耦合性,方便变更,更容易重构代码,最大程度上实现代码的重用 M表示model,主要用于对数据库层的封装 V表示 ...
- mkdir与makedirs
mkdir创建的是一级目录 makedirs可以创建多级目录 mkdir -p可以递归创建目录
- 在实现栈中原来功能的基础上,获得一个栈中最小值,要求时间复杂度 bigO(1)
思路: 准备两个栈 stackData stackMin package my_basic; import java.util.Stack; public class GetMinStack { St ...