首先把每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整数(线段树)的更多相关文章

  1. [BZOJ4942][Noi2017]整数 线段树+压位

    用线段树来模拟加减法过程,维护连续一段中是否全为0/1. 因为数字很大,我们60位压一位来处理. #include<iostream> #include<cstring> #i ...

  2. 【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

    [BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依 ...

  3. [Bzoj4942][Noi2017]整数(线段树)

    4942: [Noi2017]整数 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 363  Solved: 237[Submit][Status][D ...

  4. 2018.10.30 bzoj4942: [Noi2017]整数(线段树压位)

    传送门 直接把修改的数拆成logloglog个二进制位一个一个修改是会TLETLETLE的. 因此我们把303030个二进制位压成一位储存在线段树里面. 然后维护区间中最靠左二进制位不为0/1的下标. ...

  5. UOJ #314. 【NOI2017】整数 | 线段树 压位

    题目链接 UOJ 134 题解 可爱的电音之王松松松出的题--好妙啊. 首先想一个朴素的做法! 把当前的整数的二进制当作01序列用线段树维护一下(序列的第i位就是整数中位权为\(2^k\)的那一位). ...

  6. noi2017 T1 整数 ——线段树

    loj.ac上有  题目传送门 不过我还是把题目搬过来吧 整数(integer)[题目背景]在人类智慧的山巅,有着一台字长为 1048576 位的超级计算机,著名理论计算机科 学家 P 博士正用它进行 ...

  7. BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流

    题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...

  8. 【noi2017】 整数 线段树or模拟

    ORZYYB 题目大意:你需要维护一个有$3\times 10^7$个二进制位的数,有一种修改方式和一种询问方式 对这个数加上$a\times2^b$,其中$|a|≤10^9$,$b≤3\times ...

  9. [BZOJ4942] [NOI2017]整数

    题目背景 在人类智慧的山巅,有着一台字长为1048576位(此数字与解题无关)的超级计算机,著名理论计算机科 学家P博士正用它进行各种研究.不幸的是,这天台风切断了电力系统,超级计算机 无法工作,而 ...

随机推荐

  1. openssl生成签名与验证签名

    继上一篇RSA对传输信息进行加密解密,再写个生成签名和验证签名. 一般,安全考虑,比如接入支付平台时,请求方和接收方要互相验证是否是你,就用签名来看. 签名方式一般两种,对称加密和非对称加密.对称加密 ...

  2. java算法----排序----(1)插入排序

    package log; public class Test4 { /** * java算法---插入排序 * * @param args */ public static void main(Str ...

  3. [转]The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    完整错误信息: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"AS IS" AND ANY ...

  4. 大话设计模式之模板模式 C#

    学无止境,精益求精 十年河东,十年河西,莫欺少年穷 今天一起探讨模板模式,如下: 一.概念 上一篇文章讲了大话设计模式:原型模式,原型模式主要是通过Clone()方法<深浅复制>,创建新的 ...

  5. 马加爵遗书 VS 药家鑫遗书

          前言:今天是贰零壹柒年最后一个工作日,亦是2017年12月29日,因为明天就放元旦假了,公司同事比往常相对轻松些.中午吃完午饭,在办公室大家有说有笑,有人说姓马的人都挺牛X啊,比如:马云, ...

  6. [Oracle]GoldenGate官方文档

    Extracting Data in Oracle GoldenGate Integrated Capture Mode http://www.oracle.com/technetwork/datab ...

  7. FSMC的个人理解

    个人理解: FSMC相当于外部设备存储器地址在FSMC对应存储地址中的映射,通过在FSMC的存储地址中写数据,就能通过FSMC的地址线和数据线,将地址和数据写到外部设备存储器地址中.所以,程序中,需要 ...

  8. Spring学习日志之纯Java配置的MVC框架搭建

    依赖引入 <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifa ...

  9. 仓储层接口IBaseRepository解析

    //代码调用由业务层调用,调用方式详见源代码的业务层,升级直接替换TT模板即可,无需覆盖系统using System; using System.Collections.Generic; using ...

  10. dpkg:错误:正在解析文件 '/var/lib/dpkg/updates/0014' 第 0 行附近:在字段名 #padding 中有换行符问题的解决方法

    解决方案如下: sudo rm /var/lib/dpkg/updates/* sudo apt-get update python@ubuntu:~/Desktop/_Welcome_.jpg.ex ...