BZOJ4942 NOI2017整数(线段树)
首先把每32位压成一个unsigned int(当然只要压起来能过就行)。如果不考虑进/退位的话,每次只要将加/减上去的数拆成两部分直接单点修改就好了。那么考虑如何维护进/退位。可以发现进位的过程其实就是将一段连续的inf改为0,并把之后一位+1,也就是说只要找到某一位之后第一个不是inf的位就好了。我们用线段树维护这个东西,记录一下某个节点表示的区间是否全为inf。查询时先从叶子节点往上爬,直到当前节点代表的区间中在该叶子节点右边的位不全为inf时停止,之后再往下找最左的非inf位。退位类似。这样的话复杂度就是O(nlogn)。
写起来挺烦的,注意一下各种细节,码力极弱选手表示调了快一天……惨惨。
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 1000010
#define ui unsigned int
#define inf 4294967295
#define lson (k<<1)
#define rson (k<<1|1)
#define getmid; int mid=tree[k].l+tree[k].r>>1;
int n;
struct data{int l,r,tag,size,sumzero,suminf;ui num;
}tree[N<<];
bool isleaf(int k){return tree[k].size==;}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r,tree[k].size=r-l+;
tree[k].sumzero=tree[k].size,tree[k].suminf=;
if (isleaf(k)) return;
getmid;
build(lson,l,mid);
build(rson,mid+,r);
}
void up(int k)
{
tree[k].sumzero=tree[lson].sumzero+tree[rson].sumzero;
tree[k].suminf=tree[lson].suminf+tree[rson].suminf;
}
void update(int k,int tag)
{
if (tag>) tree[k].sumzero=tree[k].size,tree[k].suminf=;
else tree[k].sumzero=,tree[k].suminf=tree[k].size;
tree[k].tag=tag;
if (isleaf(k)) tree[k].num=tag>?:inf;
}
void down(int k)
{
if (tree[k].tag)
{
update(lson,tree[k].tag);
update(rson,tree[k].tag);
tree[k].tag=;
}
}
int find(int k,int x)
{
if (isleaf(k)) return k;
down(k);
getmid;
int ans;
if (x<=mid) ans=find(lson,x);
else ans=find(rson,x);
up(k);
return ans;
}
void modify(int k,int l,int r,int tag)
{
if (tree[k].l==l&&tree[k].r==r)
{
update(k,tag);
return;
}
down(k);
getmid;
if (r<=mid) modify(lson,l,r,tag);
else if (l>mid) modify(rson,l,r,tag);
else modify(lson,l,mid,tag),modify(rson,mid+,r,tag);
up(k);
}
int add(int k,int p,ui x)
{
if (isleaf(k))
{
int v=inf-tree[k].num<x;
tree[k].num+=x;
tree[k].sumzero=(tree[k].num==);
tree[k].suminf=(tree[k].num==inf);
return v;
}
down(k);
getmid;
int ans;
if (p<=mid) ans=add(lson,p,x);
else ans=add(rson,p,x);
up(k);
return ans;
}
int dec(int k,int p,ui x)
{
if (isleaf(k))
{
int v=tree[k].num<x;
tree[k].num-=x;
tree[k].sumzero=(tree[k].num==);
tree[k].suminf=(tree[k].num==inf);
return v;
}
down(k);
getmid;
int ans;
if (p<=mid) ans=dec(lson,p,x);
else ans=dec(rson,p,x);
up(k);
return ans;
}
void pushup(int k)
{
if (tree[k].suminf)
{
int t=k,cnt=;
while (tree[k].suminf-cnt==tree[k].r-tree[t].l+)
{
if (k&) cnt+=tree[k-].suminf;
k>>=;
}
k=rson;
while (!isleaf(k))
{
down(k);
if (tree[lson].suminf==tree[lson].size) k=rson;
else k=lson;
}
modify(,tree[t].l,tree[k].l-,);
}
add(,tree[k].l,);
}
void pushdown(int k)
{
if (tree[k].sumzero)
{
int t=k,cnt=;
while (tree[k].sumzero-cnt==tree[k].r-tree[t].l+)
{
if (k&) cnt+=tree[k-].sumzero;
k>>=;
}
k=rson;
while (!isleaf(k))
{
down(k);
if (tree[lson].sumzero==tree[lson].size) k=rson;
else k=lson;
}
modify(,tree[t].l,tree[k].l-,-);
}
dec(,tree[k].l,);
}
int query(int k,int p,int x)
{
if (isleaf(k)) return tree[k].num>>x&;
down(k);
getmid;
int ans;
if (p<=mid) ans=query(lson,p,x);
else ans=query(rson,p,x);
up(k);
return ans;
}
int main()
{
n=read();read(),read(),read();
build(,,n+);
for (int i=;i<=n;i++)
{
int op=read();
if (op==)
{
int x=read(),y=read();
if (x>)
{
ui v=x;
ui a=v<<(y&),b=(y&)?(v>>(-(y&))):;
if (a>) b+=add(,(y>>)+,a);
if (b>)
{
a=add(,(y>>)+,b);
if (a>) pushup(find(,(y>>)+));
}
}
else
{
ui v=abs(x);
ui a=v<<(y&),b=(y&)?(v>>(-(y&))):;
if (a>) b+=dec(,(y>>)+,a);
if (b>)
{
a=dec(,(y>>)+,b);
if (a>) pushdown(find(,(y>>)+));
}
}
}
else
{
int x=read();
printf("%d\n",query(,(x>>)+,x&));
}
}
return ;
}
BZOJ4942 NOI2017整数(线段树)的更多相关文章
- [BZOJ4942][Noi2017]整数 线段树+压位
用线段树来模拟加减法过程,维护连续一段中是否全为0/1. 因为数字很大,我们60位压一位来处理. #include<iostream> #include<cstring> #i ...
- 【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)
[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依 ...
- [Bzoj4942][Noi2017]整数(线段树)
4942: [Noi2017]整数 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 363 Solved: 237[Submit][Status][D ...
- 2018.10.30 bzoj4942: [Noi2017]整数(线段树压位)
传送门 直接把修改的数拆成logloglog个二进制位一个一个修改是会TLETLETLE的. 因此我们把303030个二进制位压成一位储存在线段树里面. 然后维护区间中最靠左二进制位不为0/1的下标. ...
- UOJ #314. 【NOI2017】整数 | 线段树 压位
题目链接 UOJ 134 题解 可爱的电音之王松松松出的题--好妙啊. 首先想一个朴素的做法! 把当前的整数的二进制当作01序列用线段树维护一下(序列的第i位就是整数中位权为\(2^k\)的那一位). ...
- noi2017 T1 整数 ——线段树
loj.ac上有 题目传送门 不过我还是把题目搬过来吧 整数(integer)[题目背景]在人类智慧的山巅,有着一台字长为 1048576 位的超级计算机,著名理论计算机科 学家 P 博士正用它进行 ...
- BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流
题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...
- 【noi2017】 整数 线段树or模拟
ORZYYB 题目大意:你需要维护一个有$3\times 10^7$个二进制位的数,有一种修改方式和一种询问方式 对这个数加上$a\times2^b$,其中$|a|≤10^9$,$b≤3\times ...
- [BZOJ4942] [NOI2017]整数
题目背景 在人类智慧的山巅,有着一台字长为1048576位(此数字与解题无关)的超级计算机,著名理论计算机科 学家P博士正用它进行各种研究.不幸的是,这天台风切断了电力系统,超级计算机 无法工作,而 ...
随机推荐
- SkylineGlobe 如何实现二次开发加载KML文件
示例代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- 《MySQL必知必会》[07] 管理事务处理
1.管理事务处理 一个或多个数据库操作(查询/更新等)组成"事务",也就是说,事务实际上是一组按顺序执行的操作单位: 原子性:整个事务为整体执行,要么执行,要么不执行,不能出现执行 ...
- HTML5-应用程序缓存(Application Cache)
一.什么是应用程序缓存? HTML5 引入了应用程序缓存(Application Cache),这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问. 二.优势 离线浏览 - 用户可在应用 ...
- NOIp2018停课刷题记录
Preface 老叶说了高中停课但是初中不停的消息后我就为争取民主献出一份力量 其实就是和老师申请了下让我们HW的三个人听课结果真停了 那么还是珍惜这次机会好好提升下自己吧不然就\(AFO\)了 Li ...
- 如何打造网站克隆、仿站工具(C#版)
前两天朋友叫我模仿一个网站,刚刚开始,我一个页面一个页面查看源码并复制和保存,花了我很多时间,一个字“累”,为了减轻工作量,我写了个网站“克隆工具”,一键克隆,比起人工操作, 效率提高了200%以上, ...
- 浅谈java反射机制
目录 什么是反射 初探 初始化 类 构造函数 属性 方法 总结 思考 什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意 ...
- Oracle数据库冷备份与热备份操作梳理
Oracle数据库的备份方式有冷备份和热备份两种,针对这两种备份的实施过程记录如下: 一.Oracle冷备份 概念数据库在关闭状态下完成所有物理系统文件拷贝的过程,也称脱机备份.适合于非归档模式(即n ...
- mysql主从同步(5)-同步延迟状态考量(seconds_behind_master和pt-heartbea)
一般情况下,我们是通过"show slave status \G;"提供的Seconds_Behind_Master值来衡量mysql主从同步的延迟情况.具体说明见:mysql主从 ...
- nginx try_files 详解
server { listen ; server_name localhost; index index.html index.htm index.php; root /data/wwwroot; l ...
- #个人博客作业week2——关于代码规范的个人观点
对于这一讨论的前提我们首先要知道什么是代码规范. 在这个问题上我同意一篇参考文章的观点——代码规范不仅只编码风格.编码风格仅是代码规范的一个方面,除了编码风格,代码规范还包括函数返回值等其他方面.在我 ...