【bzoj4942】[Noi2017]整数 压位+线段树
题目描述
P 博士将他的计算任务抽象为对一个整数的操作。
具体来说,有一个整数 $x$ ,一开始为0。
接下来有 $n$ 个操作,每个操作都是以下两种类型中的一种:
1 a b :将 $x$ 加上整数 $a⋅2^b$ ,其中 $a$ 为一个整数,$b$ 为一个非负整数
2 k :询问 $x$ 在用二进制表示时,位权为 $2^k$ 的位的值(即这一位上的 $1$ 代表 $2^k$ )
保证在任何时候,$x≥0$。
输入
从标准输入读入数据。
输入的第一行包含四个正整数 $n,t_1,t_2,t_3$ ,$n$ 的含义见题目描述,$t_1,t_2,t_3$ 的具体含义见子任务。
接下来 $n$ 行,每行给出一个操作,具体格式和含义见题目描述。
同一行输入的相邻两个元素之间,用恰好一个空格隔开。
输出
输出到标准输出。
对于每个询问操作,输出一行,表示该询问的答案(0或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
样例输出
0
1
0
1
0
题解
压位+线段树
考场上想出了 $n\log^2n$ 的做法,然而没有想出压位就GG了。。。
先说 $n\log^2n$ 的做法:
由于 $|a|$ 只有 $10^9$ ,因此把 $a$ 分解成 $\sum 2^i$ 的形式,就变成了 $\log n$ 次加/减 $2^k$ 。
考虑加法,如果这一位是0则直接改为1,否则进位,相当于这一位变成0,下一位+1。最终结果就是找到这一位下面第一个为0的位,把该位+1,[当前位,该位)变成0。
减法同理,如果是1则直接该为0,否则退位,找到这一位下面第一个为1的为,把该位-1,[当前位,该位)变成1。
使用线段树维护区间是否全为0/1,单次加减的时间复杂度就是 $\log n$ ,$n$ 次 $\log n$ 次加减,时间复杂度 $O(n\log^2n)$ ,这样只有68分。
考虑优化:维护01信息过于浪费,考虑压位,维护每连续30位的数是什么。这样一次操作最多给两个位加减,加法就判断这一位加了以后是否超过 $2^{30}-1$ ,超过就找下面第一个不为 $2^{30}-1$ 的位,把该位+1,(当前位,该位)变成0,当前位直接变成进位后的结果。减法同理。
其中维护一段区间是否全 $0$ /全 $2^{30}-1$ 可以通过维护区间或和区间与来解决。
这样压位后时间复杂度就变为了 $O(n\log n)$
#include <cstdio>
#include <cctype>
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
const int m = 1000010 , s = (1 << 30) - 1;
int vo[m << 2] , va[m << 2] , tag[m << 2];
char pbuf[2000010] , *pp = pbuf;
inline char nc()
{
static char buf[100000] , *p1 , *p2;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ;
}
inline int read()
{
int ret = 0 , f = 0; char ch = nc();
while(!isdigit(ch)) f |= (ch == '-') , ch = nc();
while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = nc();
return f ? -ret : ret;
}
inline void pushup(int x)
{
vo[x] = vo[x << 1] | vo[x << 1 | 1];
va[x] = va[x << 1] & va[x << 1 | 1];
}
inline void pushdown(int x)
{
if(~tag[x])
{
int l = x << 1 , r = x << 1 | 1;
vo[l] = vo[r] = va[l] = va[r] = tag[l] = tag[r] = tag[x];
tag[x] = -1;
}
}
inline void fix(int p , int v , int l , int r , int x)
{
if(l == r)
{
vo[x] += v , va[x] += v;
return;
}
pushdown(x);
int mid = (l + r) >> 1;
if(p <= mid) fix(p , v , lson);
else fix(p , v , rson);
pushup(x);
}
inline void update(int b , int e , int v , int l , int r , int x)
{
if(b <= l && r <= e)
{
vo[x] = va[x] = tag[x] = v;
return;
}
pushdown(x);
int mid = (l + r) >> 1;
if(b <= mid) update(b , e , v , lson);
if(e > mid) update(b , e , v , rson);
pushup(x);
}
inline int findzero(int p , int l , int r , int x)
{
if(!vo[x]) return -1;
if(l == r) return l;
pushdown(x);
int mid = (l + r) >> 1;
if(p <= mid)
{
int t = findzero(p , lson);
return ~t ? t : findzero(p , rson);
}
else return findzero(p , rson);
}
inline int findinf(int p , int l , int r , int x)
{
if(va[x] == s) return -1;
if(l == r) return l;
pushdown(x);
int mid = (l + r) >> 1;
if(p <= mid)
{
int t = findinf(p , lson);
return ~t ? t : findinf(p , rson);
}
else return findinf(p , rson);
}
inline int query(int p , int l , int r , int x)
{
if(l == r) return va[x];
pushdown(x);
int mid = (l + r) >> 1;
if(p <= mid) return query(p , lson);
else return query(p , rson);
}
inline void add(int p , int a)
{
int t = query(p , 0 , m , 1);
if(t + a <= s) fix(p , a , 0 , m , 1);
else
{
fix(p , a - s - 1 , 0 , m , 1);
int q = findinf(p + 1 , 0 , m , 1);
if(q != p + 1) update(p + 1 , q - 1 , 0 , 0 , m , 1);
fix(q , 1 , 0 , m , 1);
}
}
inline void del(int p , int a)
{
int t = query(p , 0 , m , 1);
if(t - a >= 0) fix(p , -a , 0 , m , 1);
else
{
fix(p , s + 1 - a , 0 , m , 1);
int q = findzero(p + 1 , 0 , m , 1);
if(q != p + 1) update(p + 1 , q - 1 , s , 0 , m , 1);
fix(q , -1 , 0 , m , 1);
}
}
int main()
{
int n = read() , opt , x , y , p;
read() , read() , read();
while(n -- )
{
opt = read() , x = read();
if(opt == 1)
{
y = read() , p = y / 30;
if(x > 0)
{
add(p , (x << (y - p * 30)) & s);
add(p + 1 , x >> (30 - (y - p * 30)));
}
else if(x < 0)
{
x = -x;
del(p , (x << (y - p * 30)) & s);
del(p + 1 , x >> (30 - (y - p * 30)));
}
}
else
{
p = x / 30;
*pp ++ = (query(p , 0 , m , 1) & (1 << (x - p * 30)) ? 1 : 0) ^ '0' , *pp ++ = '\n';
}
}
fwrite(pbuf , 1 , pp - pbuf , stdout);
return 0;
}
【bzoj4942】[Noi2017]整数 压位+线段树的更多相关文章
- BZOJ 4942 NOI2017 整数 (压位+线段树)
题目大意:让你维护一个数x(x位数<=3*1e7),要支持加/减a*2^b,以及查询x的第i位在二进制下是0还是1 作为一道noi的题,非常考验写代码综合能力,敲+调+借鉴神犇的代码 3个多小时 ...
- LOJ 2302 「NOI2017」整数——压位线段树
题目:https://loj.ac/problem/2302 压30位,a最多落在两个位置上,拆成两次操作. 该位置加了 a 之后,如果要进位或者借位,查询一下连续一段 0 / 1 ,修改掉,再在含有 ...
- 【NOI】2017 整数(BZOJ 4942,LOJ2302) 压位+线段树
[题目]#2302. 「NOI2017」整数 [题意]有一个整数x,一开始为0.n次操作,加上a*2^b,或询问2^k位是0或1.\(n \leq 10^6,|a| \leq 10^9,0 \leq ...
- 2018.10.30 bzoj4942: [Noi2017]整数(线段树压位)
传送门 直接把修改的数拆成logloglog个二进制位一个一个修改是会TLETLETLE的. 因此我们把303030个二进制位压成一位储存在线段树里面. 然后维护区间中最靠左二进制位不为0/1的下标. ...
- [BZOJ4942][Noi2017]整数 线段树+压位
用线段树来模拟加减法过程,维护连续一段中是否全为0/1. 因为数字很大,我们60位压一位来处理. #include<iostream> #include<cstring> #i ...
- [Bzoj4942][Noi2017]整数(线段树)
4942: [Noi2017]整数 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 363 Solved: 237[Submit][Status][D ...
- BZOJ4942 NOI2017整数(线段树)
首先把每32位压成一个unsigned int(当然只要压起来能过就行).如果不考虑进/退位的话,每次只要将加/减上去的数拆成两部分直接单点修改就好了.那么考虑如何维护进/退位.可以发现进位的过程其实 ...
- Wannafly挑战赛22 D 整数序列 (线段树维护三角函数值)
链接:https://ac.nowcoder.com/acm/contest/160/D 来源:牛客网 整数序列 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语 ...
- [BZOJ4942] [NOI2017]整数
题目背景 在人类智慧的山巅,有着一台字长为1048576位(此数字与解题无关)的超级计算机,著名理论计算机科 学家P博士正用它进行各种研究.不幸的是,这天台风切断了电力系统,超级计算机 无法工作,而 ...
随机推荐
- HttpURLConnection、HttpClient和Session
原文地址:http://www.cnblogs.com/kross/p/3615695.html 一直没弄懂Session,cookies什么的登陆验证到底是怎么回事,昨天分别用HttpURLConn ...
- Struts2+json+hignchart(简单柱状图实现--适合jquery小白)
做了一个简单的基于Struts2 + Json + HighChart的小例子,费了一下午+晚上的时间,虽然简单,但对于我这种Jquery+Ajax小白的人还是很值得记录的. 哈哈哈 # 0. 关键点 ...
- vue & button & refs & click & bug
vue & button & refs & click & bug $refs.btn.click() ??? vue & refs $refs.btn.$em ...
- MySQL复合主键下ON DUPLICATE KEY UPDATE语句失效问题
问题的起因,假设有一张表,里面保存了交易订单,每张订单有唯一的ID,有最后更新时间,还有数据,详情如下: 1 2 3 4 5 6 7 +-------+----------+------+-----+ ...
- Everyone is tester
有一本书叫<人人都是产品经理>,作者在书中介绍了在做产品的过程中学到的思维方式和做事方式,受到行业大众的认可 作为一名测试老鸟,我想说,其实Everyone is tester 为 ...
- P3758 [TJOI2017]可乐
题目描述 加里敦星球的人们特别喜欢喝可乐.因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的1号城市上.这个可乐机器人有三种行为: 停在原地,去下一个相邻的城市,自爆.它每一秒都会随机 ...
- 【BZOJ2024】舞会(动态规划,容斥,高精度)
[BZOJ2024]舞会(动态规划,容斥,高精度) 题面 BZOJ 洛谷 题解 这种关系显然要先排序才不会不想影响. 设\(f[i][j]\)表示前\(i\)个女生中,选了\(j\)个女生配对,并且女 ...
- CF739E Gosha is hunting 【WQS二分 + 期望】
题目链接 CF739E 题解 抓住个数的期望即为概率之和 使用\(A\)的期望为\(p[i]\) 使用\(B\)的期望为\(u[i]\) 都使用的期望为\(p[i] + u[i] - u[i]p[i] ...
- 洛谷 P1878 舞蹈课 解题报告
P1878 舞蹈课 题目描述 有\(n\)个人参加一个舞蹈课.每个人的舞蹈技术由整数来决定.在舞蹈课的开始,他们从左到右站成一排.当这一排中至少有一对相邻的异性时,舞蹈技术相差最小的那一对会出列并开始 ...
- 构建工具-----Gradle(二)-----myeclipse 10和myeclipse2015安装gradle插件----其他版本的myeclipse类似
我们需要给myeclipse安装gradle的插件.这样myeclipse就能识别到gradle项目了,直接加载进去即可. 我们先安装配置系统命令行的gradle,挺简单的,下载后配置环境变量即可,详 ...