loj.ac上有  题目传送门

不过我还是把题目搬过来吧

整数(integer)
【题目背景】
在人类智慧的山巅,有着一台字长为 1048576 位的超级计算机,著名理论计算机科 学家 P 博士正用它进行各种研究。不幸的是,这天台风切断了电力系统,超级计算机 无法工作,而 P 博士明天就要交实验结果了,只好求助于学过 OI 的你......
【题目描述】 P 博士将他的计算任务抽象为对一个整数的操作。

具体来说,有一个整数 x ,一开始为 0。 接下来有 n 个操作,每个操作都是以下两种类型中的一种:

• 1 a b :将 x 加上整数 a·2b,其中 a 为一个整数,b 为一个非负整数

• 2 k :询问 x 在用二进制表示时,位权为 2k 的位的值(即这一位上的 1 代表 2k )

保证在任何时候,x≥0。
【输入格式】 从标准输入读入数据。

输入的第一行包含四个正整数 n,t1,t2,t3,n 的含义见题目描述,t1,t2,t3 的具体含义 见子任务。

接下来 n 行,每行给出一个操作,具体格式和含义见题目描述。

同一行输入的相邻两个元素之间,用恰好一个空格隔开。
【输出格式】

输出到标准输出。

对于每个询问操作,输出一行,表示该询问的答案(000 或 111)。 对于加法操作,没有任何输出

样例输入 1

10 3 1 2

1 100 0

1 2333 0

1 -233 0

2 5

2 7

2 15

1 5 15

2 15

1 -1 12

2 15

【样例 1 输出】

0

1

0

1

0

【子任务】 在所有测试点中,

1 ≤ t1 ≤ 3,1 ≤ t2 ≤ 4,1 ≤ t3 ≤ 2。

不同的 t1,t2,t3 对应的特殊限制 如下:

• 对于 t1 = 1 的测试点,满足 a = 1

•对于 t1 = 2 的测试点,满足 |a|= 1

• 对于 t1 = 3 的测试点,满足 |a|≤109 • 对于 t2 = 1 的测试点,满足 0≤b,k≤30

• 对于 t2 = 2 的测试点,满足 0≤b,k≤100

• 对于 t2 = 3 的测试点,满足 0≤b,k≤n

• 对于 t2 = 4 的测试点,满足 0≤b,k≤30n

• 对于 t3 = 1 的测试点,保证所有询问操作都在所有修改操作之后

• 对于 t3 = 2 的测试点,不保证询问操作和修改操作的先后顺序

这道题首先 a*2^b 这个东西呢按我的想法是把 a 拆成2的x次幂的和 然后+b

如果只有加法当然很好写 但是这道题 a 可能是负的

所以我开了两个数组 s1 s2 来存 s1 存的是正的 s2 存的是负的

注意存的时候进位 均摊复杂度只有o(1) 所以暴力进位就好了

然后问题就转换成了已知两个高精度数,问他们的差的某一位是什么

然后分类可得

我们记一个数为 1(0)x

1 (0)  表示询问的这一位的值(因为是二进制,所以不是1就是0)

x就是询问位后面那一串东西(一坨1 0 混合体)

考虑减法是否退位的时候呢

1. x>=y:
1x-1y=0(x-y)
1x-0y=1(x-y)
0x-1y=1(x-y)
0x-0y=0(x-y)
2. x<y:
1x-1y=1(x-y+2^k)
1x-0y=0(x-y+2^k)
0x-1y=0(x-y+2^k)
0x-0y=1(x-y+2^k)

举个例子吧

10-10=00
10-00=10
01-10=11
01-01=00

10-11=11
10-01=01
00-11=01
00-01=11

注 题目保证x始终大于等于0 所以s1总和也一定大于s2

这样分析之后呢 问题就转换成了从1-x(即询问位)-1这个区间里s1 s2 的大小关系

如果 s1>=s2

那么答案就是 s1^s2(^念做异或)

如果 s2<=s2

那么答案就是 s1==s2 (==念做同或)

那么 x 和 y 的比较 其实就是比较字典序 找到第一个不一样的地方 哪个是1 哪个就大 (这么很好证明我就不详细讲了) 注意这里讲的都是二进制

算了举个例子吧 如果x是1000 y是0111 那么x是不是一定大于y

所以我们可以采用线段树维护区间内s1 s2 的大小

当然我这里采用的是zkw线段树 (自带底层优化自然会比较快 而且修改也很好写)

毕竟三千万(3e7)个叶子结点 同时线段树中下标也就是二进制中 2的次数

操作自然就是 区间内单点修改,前缀查询

那么我们每次操作1拆完a加上b以及进位之后

我们要记录一波 修改到的最左位置到最右位置 进位自然也算修改

然后就在线段树上暴力修改顺便上传信息 复杂度是 o( r-l + log(n))

操作2 询问的时候我们就找到区间中靠右(也就是比较大的位置)的第一个不一样的地方然后判断一波就好了

到这里题目就完美解决了 修改(modify)以及 查找(find) 就看代码吧

注: find我的写法呢 是向上走时,如果x是右孩子且x的兄弟为1才向下走

实测跑得也蛮快的 23333

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
const int M=3e7+,N=<<;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
int s1[M],s2[M],cnt;
int l,r,a,b,n,k;
void prepare(int x){
if(!x) return ;
int v=x>?x:-x,w[];
cnt=;
for(int i=;i>=;i--){
int now=<<i;
if(now&v) v-=now,w[++cnt]=i;
if(!v) break;
}
l=w[cnt]+b; r=w[]+b;
if(x>)
for(int i=;i<=cnt;i++){
int now=w[i]+b;
while(s1[now]) s1[now++]=,r=max(r,now);
s1[now]=;
}
else
for(int i=;i<=cnt;i++){
int now=w[i]+b;
while(s2[now]) s2[now++]=,r=max(r,now);
s2[now]=;
}
}
int tr[*N],T,now;
void modify(){
for(int i=l;i<=r;i++) tr[i+N]=s1[i]^s2[i];
for(l=(l+N)>>,r=(r+N)>>;l;l>>=,r>>=)
for(int i=l;i<=r;i++) tr[i]=tr[i<<]|tr[i<<^];
}
int find(int k){
for(k+=N;k;k>>=) if(k&&tr[k^]){
for(k^=;k<N;k=k<<^tr[k<<^]);
return k-N;
}
return -;
}
int main()
{
n=read(); T=read(); T=read(); T=read();
for(int i=;i<=n;i++){
k=read();
if(k==){
a=read(); b=read();
prepare(a);
modify();
}
else{
a=read();
now=find(a);
if(s1[now]>s2[now]||now==-) printf("%d\n",s1[a]^s2[a]);
else printf("%d\n",s1[a]==s2[a]);
}
}
return ;
}

noi2017 T1 整数 ——线段树的更多相关文章

  1. UOJ #314. 【NOI2017】整数 | 线段树 压位

    题目链接 UOJ 134 题解 可爱的电音之王松松松出的题--好妙啊. 首先想一个朴素的做法! 把当前的整数的二进制当作01序列用线段树维护一下(序列的第i位就是整数中位权为\(2^k\)的那一位). ...

  2. 【noi2017】 整数 线段树or模拟

    ORZYYB 题目大意:你需要维护一个有$3\times 10^7$个二进制位的数,有一种修改方式和一种询问方式 对这个数加上$a\times2^b$,其中$|a|≤10^9$,$b≤3\times ...

  3. 【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

    [BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依 ...

  4. [BZOJ4942][Noi2017]整数 线段树+压位

    用线段树来模拟加减法过程,维护连续一段中是否全为0/1. 因为数字很大,我们60位压一位来处理. #include<iostream> #include<cstring> #i ...

  5. 省选模拟赛 4.26 T1 dp 线段树优化dp

    LINK:T1 算是一道中档题 考试的时候脑残了 不仅没写优化 连暴力都打挂了. 容易发现一个性质 那就是同一格子不会被两种以上的颜色染.(颜色就三种. 通过这个性质就可以进行dp了.先按照左端点排序 ...

  6. F. Wi-Fi(线段树实现dp)

    题:http://codeforces.com/contest/1216/problem/F dp[i][0]:表示第i个位置不装的最小代价 dp[i][1]:表示第i个位置装的最小代价 T1的线段树 ...

  7. [Bzoj4942][Noi2017]整数(线段树)

    4942: [Noi2017]整数 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 363  Solved: 237[Submit][Status][D ...

  8. 【bzoj4942】[Noi2017]整数 压位+线段树

    题目描述 P 博士将他的计算任务抽象为对一个整数的操作. 具体来说,有一个整数 $x$ ,一开始为0. 接下来有 $n$ 个操作,每个操作都是以下两种类型中的一种: 1 a b :将 $x$ 加上整数 ...

  9. 【洛谷3822】[NOI2017] 整数(线段树压位)

    题目: 洛谷 3822 分析: 直接按题意模拟,完了. 将每次加 / 减拆成不超过 \(32\) 个对单独一位的加 / 减. 考虑给一个二进制位(下称「当前位」)加 \(1\) 时,如果这一位本来就是 ...

随机推荐

  1. request中的那些方法到底是干什么的?

    最近做Java Web项目,在.jsp页面和servlet之间request和response还是有些混淆,查阅了一些资料,总结如下,方便以后使用: 首先,servlet接口是最基本的,提供的五个方法 ...

  2. Linux编译移植Qt4的环境_在OMAPL138平台

    Linux编译Qt4的环境_OMAPL138 手里有一块创龙OMAPL138的板子,我要在上面成功移植Qt环境和触摸屏幕,这是我第二次进行Linux的Qt环境移植,发现了很多问题,需要重新整理. 我编 ...

  3. jupyter notebook中出现ValueError: signal only works in main thread 报错 即 长时间in[*] 解决办法

    我在jupyter notebook中新建了一个基于py3.6的kernel用来进行tensorflow学习 但是在jupyter notebook中建立该kernel时,右上角总是显示 服务正在启动 ...

  4. Charles Dickens【查尔斯·狄更斯】

    Charles Dickens In 1812, the year Charles Dickens was born, there were 66 novels published in Britai ...

  5. 2、spring boot 配置文件

    配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoot自 ...

  6. 04,Python网络爬虫之requests模块(1)

    引入 Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用. 警告:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症.冗余代码症.重新发明轮子症.啃文档 ...

  7. 05,Python网络爬虫之三种数据解析方式

    回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据 ...

  8. label标签的作用

    在用户注册的时候,常常用户点击文字就需要将光标聚焦到对应的表单上面,这个是怎么实现的呢?就是下面我要介绍的<label>标签的for属性 定义:for 属性规定 label 与哪个表单元素 ...

  9. Eclipse 创建 Java 包---Eclipse教程第09课

    打开新建 Java 包向导 你可以使用新建 Java 包向导来创建 Java 包.Java 包向导打开方式有: 通过点击 "File" 菜单并选择 New > Package ...

  10. 如何写一套下拉刷新的控件?《MJRefresh原理浅析》(附Demo下载地址)

    相信大家有很多人在做项目的时候都在使用MJRefresh 控件来实现下拉刷新的功能: MJRefresh经过不断的重构与更新迭代,现在不管是功能上还是代码结构上都是相当不错的,都是很值我们去学习的. ...