BZOJ.4942.[NOI2017]整数(分块)
可能是退役之前最后一个BZOJ rank1了?
参考这里。
如果没有减法,对一个二进制数暴力进位,均摊复杂度是\(O(1)\)的(要进\(O(n)\)次位就至少需要\(O(n)\)次操作)。
但是这题有减法...显然暴力进位就不对了。
那么我们把减法变成加法,分别维护加上的数\(inc\)和减掉的数\(dec\)是多大。查询时显然不能直接两位相减,要判断一下后面是否需要进位。
对此用\(set\)维护一下\(inc,dec\)所有不同位的位置,找到查询位后面第一个不同的位置,判一下大小关系就可以了。
关于维护进位,比较显然的是拿线段树维护每一位的情况,把\(a\times2^b\)拆成\((2^{a_1}+2^{a_2}+...)2^n\)。。这样就成两个\(\log\)了(╯‵□′)╯︵┻━┻。
注意到\(a\)不算大,而且线段树的每个位置是可以表示\(16\)或\(32\)位的。直接把\(a\)左移\(b\)位(本来就是= =),也就是把\(a\)加到\(b\)那个位置即可。如果取\(32\)位这么加一次显然是只会进位一次的(最多影响两个位置)。
(\(32\)位可以直接用unsigned int,自然溢出就可以得到加之后这几位的值,判断是否进位就判一下这个数加之前与加之后的大小关系即可)
注意到这个线段树其实没什么必要。分块,每块维护\(32\)位的值,每次只要在对应块上加,然后暴力进位即可。
复杂度\(O(n\log n)\)(set...)。
另外移位不能\(\geq\)位宽,所以移\(32\)位拆成移\(31\)位再移\(1\)位好了。。
//18148kb 3740ms
#include <set>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define pc putchar
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
typedef unsigned int uint;
const int N=1e6+5;
uint inc[N],dec[N];
std::set<int> st;
char IN[MAXIN],*SS=IN,*TT=IN,OUT[N<<1],*O=OUT;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
void Modify(uint a,uint b,uint *A,uint *B)//a在传参前就要取abs啊(uint)
{//2^5=32
int p=b>>5,q=b&31;
uint tmp=A[p],delta=(a>>31-q)>>1; A[p]+=(a<<q);//uint
delta+=(A[p]<tmp); std::set<int>::iterator it;
if(A[p]!=B[p]) st.insert(p);
else if((it=st.find(p))!=st.end()) st.erase(it);
while(delta)
{
tmp=A[++p], A[p]+=delta, delta=A[p]<tmp;
if(A[p]!=B[p]) st.insert(p);
else if((it=st.find(p))!=st.end()) st.erase(it);
}
}
void Query()
{
int b=read(),p=b>>5,q=b&31,ans=((inc[p]^dec[p])>>q)&1;
uint v1=inc[p]&((1<<q)-1),v2=dec[p]&((1<<q)-1);//inc[p]%(2^q) 取出该块p后面的部分
if(v1<v2) *O++=((ans^1)+48);//借位
else if(v1>v2||/*st.empty()||*/*st.begin()>=p) *O++=(ans+48);
else
{
std::set<int>::iterator it=st.lower_bound(p); --it;
*O++=((inc[*it]>dec[*it]?ans:ans^1)+48);
}
*O++='\n';
}
int main()
{
st.insert(N);
for(int T=read(),a=(read(),read(),read()),b; T--; )
switch(read())
{
case 1: a=read(),b=read(),Modify(a>0?a:-a,b,a>0?inc:dec,a>0?dec:inc); break;
case 2: Query();
}
fwrite(OUT,1,O-OUT,stdout);
return 0;
}
BZOJ.4942.[NOI2017]整数(分块)的更多相关文章
- BZOJ 4942 NOI2017 整数 (压位+线段树)
题目大意:让你维护一个数x(x位数<=3*1e7),要支持加/减a*2^b,以及查询x的第i位在二进制下是0还是1 作为一道noi的题,非常考验写代码综合能力,敲+调+借鉴神犇的代码 3个多小时 ...
- bzoj 4942: [Noi2017]整数
Description Solution 加法减法可以分开考虑,如果只有加法的话,直接暴力进位复杂度是对的 询问的时候就是把两个二进制数做差,判断第 \(k\) 位的取值 实际上我们只需要判断 \(1 ...
- [Bzoj4942][Noi2017]整数(线段树)
4942: [Noi2017]整数 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 363 Solved: 237[Submit][Status][D ...
- 【BZOJ4942】[NOI2017]整数(分块)
[BZOJ4942][NOI2017]整数(分块) 题面 BZOJ 洛谷 题解 暴力就是真正的暴力,直接手动模拟进位就好了. 此时复杂度是模拟的复杂度加上单次询问的\(O(1)\). 所以我们需要优化 ...
- [NOI2017]整数
[NOI2017]整数 题目大意: \(n(n\le10^6)\)次操作维护一个长度为\(30n\)的二进制整数\(x\),支持以下两种操作: 将这个整数加上\(a\cdot2^b(|a|\le10^ ...
- 【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)
[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依 ...
- NOI2017整数
NOI2017 整数 题意: 让你实现两个操作: 1 \(a\) \(b\):将\(x\)加上整数\(a \cdot 2 ^ b\),其中 \(a\)为一个整数,\(b\)为一个非负整数 2 \( ...
- 【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 ...
- BZOJ 2120: 数颜色 分块
2120: 数颜色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php? ...
随机推荐
- IDEA 破解
推荐三篇文章 : 1: https://blog.csdn.net/nishiwodebocai21/article/details/71359619?fps=1&locationNu ...
- Gym - 101350E Competitive Seagulls (博弈)
There are two seagulls playing a very peculiar game. First they line up N unit squares in a line, al ...
- (二叉树 BFS) leetcode102. Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...
- 解决ssh登录慢的问题
修改文件/etc/ssh/sshd_config : UseDNS no GSSAPIAuthentication no 重启服务 service sshd restart
- MySQL_表锁_lock tables tableName read
pre.环境准备 1.建立两个表S,T,并插入一些数据 --创建表S create table S(d int) engine=innodb; ); --创建表T create table T(c i ...
- java 中使用正则表达式操作字符串
import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFl ...
- oh-my-zsh安装和简单定制
我使用的是deepin系统,deepin的终端做的已经很好了,最近想换一个新的命令的提示符风格.据说oh-my-zsh很好用,花一点时间安装,记录这个过程. oh-my-zsh的安装是非常方便的,安装 ...
- 《Java》第四周学习总结
20175301 李锦然 一:本周学习内容 1:学习第五章视频 2:做实验 第五章主要讲的是子类与父类的关系,子类的继承与多态,final类super类等内容 仓库地址https://gitee.co ...
- 对评分矩阵进行分解,SVD与LSI
摘自 推荐系统 https://www.cnblogs.com/lzllovesyl/p/5243370.html 一.SVD奇异值分解 1.SVD简介 SVD(singular value deco ...
- 找不多控件, or 控件为null
组件化开发,命名要使用moudle区分, 同名,在最后合成的时候,会出现很多问题,