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? ...
随机推荐
- NOI真题记录
NOI2001 食物链,拓展域并查集. 炮兵阵地,棋盘状压DP. NOI2002 银河英雄传说,kruskal重构树/带权并查集. 贪吃的九头龙,树形DP. NOI2003 逃学的小孩,树形DP,二次 ...
- zabbix数据库分表的实现
前提条件是主从同步操作完成(主从同步的前提是两个数据库表结构必须一样) 先看一下mysql配置文件 vi /usr/local/mysql/my.cnf 配置内容:------------------ ...
- Tensorflow基本语法
一.tf.Variables() import tensorflow as tf Weights = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) se ...
- Python 文件行数读取的三种方法
Python三种文件行数读取的方法: #文件比较小 count = len(open(r"d:\lines_test.txt",'rU').readlines()) print c ...
- 在Mac下安装mongodb
本来想用brew一键安装的,但是一直不成功,解决了一个问题随即又抛出一个问题,后来只好老老实实去官网下载安装包了,解压到/usr/local目录下. 之前下载压缩包时忘记下载到/usr/local目录 ...
- 13、 使用openpyxl存储周杰伦的歌曲信息
import requests import openpyxl res = requests.get('https://c.y.qq.com/soso/fcgi-bin/client_search ...
- java(7)数组
一.什么是数组及其作用? 定义:具有相同数据类型的一个集合 作用:存储连续的具有相同类型的数据 二.java中如何声明和定义数组 2.1 声明和定义的语法: 数据类型[ ] 数组名:( int[ ] ...
- 利用div绘制细线居中
利用div配合css代码实现细线方式: 块级元素水平居中步骤: 设置宽度width 设置margin-left:auto; 设置margin-right:auto; 实现方法是,让其左右两边的外边距自 ...
- MVC ModelState.AddModelError使用
cshtml:红色部分为使用方法 PostNextDay是 字段 <div id="postNextDay" class="col-xs-12 col-sm-6 ...
- LeetCode第十三题-将罗马数字转化为数字
问题简介:将输入的String类型的罗马数字转化为int数值 问题详解:罗马数字由七个不同的符号表示:I,V,X,L,C,D和M 符号-数值 I - 1 V - 5 X -10 L - 50 C - ...