用线段树来模拟加减法过程,维护连续一段中是否全为0/1。

因为数字很大,我们60位压一位来处理。

 #include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define maxn 505050
#define base 60
#define ll long long
using namespace std;
inline ll read() {
ll x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-;
for(;isdigit(ch);ch=getchar()) x=x*+ch-'';
return x*f;
}
ll n,m,S=(1ll<<)-;
struct Seg {
int al[];
ll tag,val;
}t[maxn*];
void put(int o,ll tmp) {
if(tmp!=-) t[o].val=tmp;
if(tmp==) {t[o].al[]=;t[o].al[]=;t[o].tag=tmp;}
else if(tmp==S) {t[o].al[]=;t[o].al[]=;t[o].tag=tmp;}
else {t[o].al[]=t[o].al[]=;t[o].tag=tmp;}
}
void pushdown(int o) {
int ls=o<<,rs=ls+;
if(t[o].tag!=-) {put(ls,t[o].tag);put(rs,t[o].tag);t[o].tag=-;}
}
void pushup(int o) {
int ls=o<<,rs=ls+;
t[o].al[]=t[ls].al[]&t[rs].al[];
t[o].al[]=t[ls].al[]&t[rs].al[];
}
void build(int l,int r,int o) {
t[o].tag=-,t[o].al[]=;t[o].al[]=;t[o].val=;
if(l==r) return;
int mid=l+r>>,ls=o<<,rs=ls+;
build(l,mid,ls);build(mid+,r,rs);
}
ll query(int l,int r,int o,int x) {
if(l==r) return t[o].val;
pushdown(o);
int mid=l+r>>,ls=o<<,rs=ls+;
if(x<=mid) return query(l,mid,ls,x);
else return query(mid+,r,rs,x);
pushup(o);
}
void change(int l,int r,int o,int L,int R,ll tmp) {
if(L<=l&&R>=r) {put(o,tmp);return;}
pushdown(o);
int mid=l+r>>,ls=o<<,rs=ls+;
if(L<=mid) change(l,mid,ls,L,R,tmp);
if(R>mid) change(mid+,r,rs,L,R,tmp);
pushup(o);
}
int find(int l,int r,int o,int pos,int k) {
if(t[o].al[!k]) return -;
if(l==r) return l;
int mid=l+r>>,ls=o<<,rs=ls+;
pushdown(o);
if(pos<=mid) {
ll tmp=find(l,mid,ls,pos,k);
if(tmp!=-) return tmp;
}
return find(mid+,r,rs,pos,k);
pushup(o);
}
void add(int pos,ll ad) {
ll tmp=query(,n,,pos);change(,n,,pos,pos,(tmp+ad)&S);
if(tmp+ad>S) {
int l=find(,n,,pos+,);
tmp=query(,n,,l);
change(,n,,l,l,tmp+);
if(pos+<=l-) change(,n,,pos+,l-,);
}
}
void del(int pos,ll ad) {
ll tmp=query(,n,,pos);
if(tmp-ad<) change(,n,,pos,pos,(S+tmp-ad+)&S);
else change(,n,,pos,pos,(tmp-ad)&S);
if(tmp-ad<) {
int l=find(,n,,pos+,);
tmp=query(,n,,l);
change(,n,,l,l,tmp-);
if(pos+<=l-) change(,n,,pos+,l-,S);
}
}
int main() {
m=read();read();read();read();n=;build(,n,);
for(int i=;i<=m;i++) {
int tp=read();
if(tp==) {
ll a=read(),b=read();
if(a>) {
ll p=b/base,q=b%base;
ll x=(a<<q)&S;add(p,x);
a>>=base-q;add(p+,a);
}
else {
a=-a;ll p=b/base,q=b%base;
ll x=(a<<q)&S;del(p,x);
a>>=base-q;del(p+,a);
}
}
else {
ll a=read();
printf("%lld\n",(query(,n,,a/base)>>(a%base))&);
}
}
}
/*
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
*/

[BZOJ4942][Noi2017]整数 线段树+压位的更多相关文章

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

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

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

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

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

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

  4. 【洛谷3822】[NOI2017] 整数(线段树压位)

    题目: 洛谷 3822 分析: 直接按题意模拟,完了. 将每次加 / 减拆成不超过 \(32\) 个对单独一位的加 / 减. 考虑给一个二进制位(下称「当前位」)加 \(1\) 时,如果这一位本来就是 ...

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

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

  6. BZOJ4942 NOI2017整数(线段树)

    首先把每32位压成一个unsigned int(当然只要压起来能过就行).如果不考虑进/退位的话,每次只要将加/减上去的数拆成两部分直接单点修改就好了.那么考虑如何维护进/退位.可以发现进位的过程其实 ...

  7. noi2017 T1 整数 ——线段树

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

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

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

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

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

随机推荐

  1. js 时间戳 转化

    new Date((1524142795*1000)).toJSON().slice(11,16)

  2. sql like参数化查询

    如下例所示,这样做了后再也不担心sql注入了.... public static DataTable GetProPriEEfocusNew(string ProName) { StringBuild ...

  3. c语言时间计算

    C语言使用time_t结构体表示时间戳,它本质上是个long类型. 我们可以使用如下函数获取当前时间的时间戳: time_t time(time_t* timer) 函数功能:得到从标准计时点(一般是 ...

  4. 2017北京国庆刷题Day6 morning

    期望得分:100+100+20=220 实际得分:100+100+20=220 模拟栈 #include<cstdio> #include<cstring> using nam ...

  5. 「LibreOJ β Round #4」子集

    https://loj.ac/problem/526 题目描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两个元素 i ...

  6. bzoj 3678 wangxz与OJ

    3678: wangxz与OJ Time Limit: 10 Sec  Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.php ...

  7. 树dp...吧 ZOJ 3949

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5568 Edge to the Root Time Limit: 1 Secon ...

  8. Python学习笔记(三十五)—内置模块(4)struct

    摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431955007 ...

  9. [洛谷P4609] [FJOI2016]建筑师

    洛谷题目链接:[FJOI2016]建筑师 题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 \(n\) 个建筑,每个建筑的高度是 \(1\) 到 \(n\) 之间的一 ...

  10. 重构改善既有代码设计--重构手法05:Introduce Explaining Variable (引入解释性变量)

      发现:你有一个复杂的表达式. 解决:将该复杂的表达式(或其中的部分)的结果放进一个临时变量,并以此变量名称来解释表达式用途. //重构前 if((platform.toUpperCase().in ...