[BZOJ4942] [NOI2017]整数
题目背景
在人类智慧的山巅,有着一台字长为1048576位(此数字与解题无关)的超级计算机,著名理论计算机科
学家P博士正用它进行各种研究。不幸的是,这天台风切断了电力系统,超级计算机
无法工作,而 P 博士明天就要交实验结果了,只好求助于学过OI的你. . . . . .
题目描述
P 博士将他的计算任务抽象为对一个整数的操作。
具体来说,有一个整数xx,一开始为00。
接下来有nn个操作,每个操作都是以下两种类型中的一种:
1 a b:将x加上整数\(a\cdot 2^b\),其中a为一个整数,b为一个非负整数2 k:询问x在用二进制表示时,位权为2^k的位的值(即这一位上的1代表 2^k)
保证在任何时候,\(x\geqslant 0\)。
输入格式
输入的第一行包含四个正整数n,t_1,t_2,t_3,n的含义见题目描述,t_1,t_2,t_3的具体含义见子任务。
接下来n行,每行给出一个操作,具体格式和含义见题目描述。
同一行输入的相邻两个元素之间,用恰好一个空格隔开。
输出格式
对于每个询问操作,输出一行,表示该询问的答案(00或11)。对于加法操作,没有任何输出。
输入样例
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
输出样例
0
1
0
1
0
Solution
奇怪的题...
注意到一个性质,二进制加法每次加一的均摊复杂度是\(O(1)\)的而不是\(O(\log n)\)的,具体可以考虑每一位被加了多少次。
那么其实我们可以压位然后暴力修改,但是均摊复杂度有一个缺点,就是不支持撤回操作,否则你可以在一次复杂度较高的操作前后跳转,然后时间复杂度就不对了。
这题的减法操作就可以视为是撤回操作。
那么我们可以维护两个高精度的数,分别表示一共加了多少减了多少,那么仔细思考一下就可以知道,对于询问我们唯一的瓶颈就是如何比较大小。
注意到字符串比较大小的暴力算法,我们只需要找到第一个不同的位就好了,那么我们可以开\(set\)来维护不同的位置,每次修改的时候更新一下就好了。
那么这题就变成了小清新模拟题,然后我调了一晚上
细节是真的挺多的....不过跑的还挺快...\(bzoj\) \(rk6\)。
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define ui unsigned int
const int maxn = 1e6+10;
int n,_,s[maxn];
ui r[maxn][2];
set<int > dif;
int cnt;
int main() {
read(n),read(_),read(_),read(_);
for(int i=1;i<=n;i++) {
int op,a,b;read(op),read(a);
if(op==1) {
int k=0;read(b);
if(a<0) a=-a,k=1;
int t=b/32;b&=31;
ui p=(ui)a<<b,q=a>>(31-b),pre;q>>=1;
pre=r[t][k],r[t][k]+=p,q+=r[t][k]<pre;
if((r[t][k]^r[t][!k])&&!s[t]) s[t]=1,dif.insert(t);
else if(r[t][k]==r[t][!k]&&s[t]) s[t]=0,dif.erase(t);t++;
while(q) {
pre=r[t][k];r[t][k]+=q;q=r[t][k]<pre;
if((r[t][k]^r[t][!k])&&!s[t]) s[t]=1,dif.insert(t);
else if(r[t][k]==r[t][!k]&&s[t]) s[t]=0,dif.erase(t);
t++;
}
} else {
cnt++;
int t=a/32;a&=31;
int ans=((r[t][0]>>a)^(r[t][1]>>a))&1;
ui x=r[t][0]&((1u<<a)-1),y=r[t][1]&((1u<<a)-1);
if(x<y) write(ans^1);
else if(x>y||dif.empty()||t<=(*dif.begin())) write(ans);
else {
set<int > :: iterator it=dif.lower_bound(t);--it;
if(r[*it][0]>r[*it][1]) write(ans);
else write(ans^1);
}
}
}
return 0;
}
[BZOJ4942] [NOI2017]整数的更多相关文章
- [Bzoj4942][Noi2017]整数(线段树)
4942: [Noi2017]整数 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 363 Solved: 237[Submit][Status][D ...
- BZOJ4942 NOI2017整数(线段树)
首先把每32位压成一个unsigned int(当然只要压起来能过就行).如果不考虑进/退位的话,每次只要将加/减上去的数拆成两部分直接单点修改就好了.那么考虑如何维护进/退位.可以发现进位的过程其实 ...
- 2018.10.30 bzoj4942: [Noi2017]整数(线段树压位)
传送门 直接把修改的数拆成logloglog个二进制位一个一个修改是会TLETLETLE的. 因此我们把303030个二进制位压成一位储存在线段树里面. 然后维护区间中最靠左二进制位不为0/1的下标. ...
- [BZOJ4942][Noi2017]整数 线段树+压位
用线段树来模拟加减法过程,维护连续一段中是否全为0/1. 因为数字很大,我们60位压一位来处理. #include<iostream> #include<cstring> #i ...
- 【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)
[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依 ...
- 【BZOJ4942】[NOI2017]整数(分块)
[BZOJ4942][NOI2017]整数(分块) 题面 BZOJ 洛谷 题解 暴力就是真正的暴力,直接手动模拟进位就好了. 此时复杂度是模拟的复杂度加上单次询问的\(O(1)\). 所以我们需要优化 ...
- [NOI2017]整数
[NOI2017]整数 题目大意: \(n(n\le10^6)\)次操作维护一个长度为\(30n\)的二进制整数\(x\),支持以下两种操作: 将这个整数加上\(a\cdot2^b(|a|\le10^ ...
- NOI2017整数
NOI2017 整数 题意: 让你实现两个操作: 1 \(a\) \(b\):将\(x\)加上整数\(a \cdot 2 ^ b\),其中 \(a\)为一个整数,\(b\)为一个非负整数 2 \( ...
- 【bzoj4942】[Noi2017]整数 压位+线段树
题目描述 P 博士将他的计算任务抽象为对一个整数的操作. 具体来说,有一个整数 $x$ ,一开始为0. 接下来有 $n$ 个操作,每个操作都是以下两种类型中的一种: 1 a b :将 $x$ 加上整数 ...
随机推荐
- 解决CentOS下可以ping通ip ping不通域名
现象:1. ping不通域名,比如 www.qq.com 2. 可以ping通ip,比如 61.135.157.156 分析:1. 查看DNS配置文件 /etc/resolve.conf, 里面的服务 ...
- python generator
def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index] for char in reverse('g ...
- create-react-app创建react项目 css模块化处理
用的css预处理器用sass,其他大同小异. 用create-react-app创建项目,执行npm run eject弹出配置文件(此操作不可逆): 配置sass,用的最新的CRA,webpack4 ...
- Jmeter登录接口返回 status415
1.现象:在查看结果树中看到: Request Headers:Connection: keep-aliveContent-Type: application/x-www-form-urlencode ...
- 【SpringCloud】第六篇: 分布式配置中心(Spring Cloud Config)
前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...
- 第5章 Linux网络编程基础
第5章 Linux网络编程基础 5.1 socket地址与API 一.理解字节序 主机字节序一般为小端字节序.网络字节序一般为大端字节序.当格式化的数据在两台使用了不同字节序的主机之间直接传递时,接收 ...
- 【CSV数据文件】
文件参数化设置方法
- centos 6.5 启动时卡在进度条位置无法进入系统解决办法。
今天公司服务器因突然断电导致phddns 花生壳 启动失败,一直卡在启动进度条页面. 解决办法 1.按F5查看卡在什么位置, 2.查看解决方法:程序卡住的情况下,直接备份资料后,卸载程序重启就可以了. ...
- Linux中常用的关机和重新启动命令
hutdown.halt.reboot以及init,它们都可以达到关机和重新启动的目的,但是每个命令的内部工作过程是不同的,下面将逐一进行介绍. 一.shutdown shutdown命令用于安全关闭 ...
- windows编程常见数据类型
windows编程常见数据类型, 总结一下方便查阅: 类型 对应指针 描述 ATOM . typedef WORD ATOM; BOOL LPBOOL 布尔类型,值要写成TRUE或FALSE,实际上是 ...