题目大意:有一个整数 $x$ ,一开始为 $0$ 。有 $n$ 个操作,有两种类型:

$1 \;a\; b$:将 $x$ 加上整数 $a\cdot 2^b$ ,其中 $a$ 为一个整数, $b$ 为一个非负整数

$2\; k$ :询问 $x$ 在用二进制表示时,第 $2^k$ 位的值($0$或$1$)

保证在任何时候, $x\geq 0$ 。

题解:压位线段树,每一个节点压$30$位,考虑到有加减操作,而对于加操作,只是把这一位前的第一个$0$变成$1$,把其间的$1$变成$0$,减相反。所以我们可以在线段树中存一下区间$AND$和区间$OR$,找到某一位前的第一个$1$或第一个$0$,线段树修改一下就行了

卡点:线段树中的$update$和$pushdown$中把$rc$写成了$rt$($QAQ$)

C++ Code:

#include <cstdio>
#include <cstring>
#define base 30
#define maxn 1000010
using namespace std;
const int inf = (1 << base) - 1;
int n, op;
struct ST {
int And[maxn << 2], Or[maxn << 2], V[maxn << 2], tg[maxn << 2];
void init() {
memset(tg, -1, sizeof tg);
}
void pushdown(int rt) {
int lc = rt << 1, rc = rt << 1 | 1, &tmp = tg[rt];
And[lc] = Or[lc] = tg[lc] = tmp;
And[rc] = Or[rc] = tg[rc] = tmp;
tmp = -1;
}
void update(int rt) {
int lc = rt << 1, rc = rt << 1 | 1;
And[rt] = And[lc] & And[rc];
Or[rt] = Or[lc] | Or[rc];
}
void add(int rt, int l, int r, int p, int num) {
if (l > r) return ;
if (l == r) {
Or[rt] = And[rt] = num;
return ;
}
int mid = l + r >> 1;
if (~tg[rt]) pushdown(rt);
if (p <= mid) add(rt << 1, l, mid, p, num);
else add(rt << 1 | 1, mid + 1, r, p, num);
update(rt);
}
void add(int rt, int l, int r, int L, int R, int num) {
if (l > r || L > R) return ;
if (L <= l && R >= r) {
Or[rt] = And[rt] = tg[rt] = num;
return ;
}
int mid = l + r >> 1;
if (~tg[rt]) pushdown(rt);
if (L <= mid) add(rt << 1, l, mid, L, R, num);
if (R > mid) add(rt << 1 | 1, mid + 1, r, L, R, num);
update(rt);
}
int ask(int rt, int l, int r, int p) {
if (l > r) return 0;
if (l == r) return And[rt];
int mid = l + r >> 1, ans;
if (~tg[rt]) pushdown(rt);
if (p <= mid) ans = ask(rt << 1, l, mid, p);
else ans = ask(rt << 1 | 1, mid + 1, r, p);
return ans;
}
int find_1(int rt, int l, int r, int p) {
if (Or[rt] == 0) return -1;
if (l == r) return l;
int mid = l + r >> 1;
if (~tg[rt]) pushdown(rt);
if (p <= mid) {
int tmp = find_1(rt << 1, l, mid, p);
return ~tmp ? tmp : find_1(rt << 1 | 1, mid + 1, r, p);
} else return find_1(rt << 1 | 1, mid + 1, r, p);
}
int find_0(int rt, int l, int r, int p) {
if (And[rt] == inf) return -1;
if (l == r) return l;
int mid = l + r >> 1;
if (~tg[rt]) pushdown(rt);
if (p <= mid) {
int tmp = find_0(rt << 1, l, mid, p);
return ~tmp ? tmp : find_0(rt << 1 | 1, mid + 1, r, p);
} else return find_0(rt << 1 | 1, mid + 1, r, p);
}
} T;
void inc(int p, int num) {
if (!num) return ;
int tmp = T.ask(1, 0, maxn, p) + num;
if (tmp <= inf) T.add(1, 0, maxn, p, tmp);
else {
T.add(1, 0, maxn, p, tmp & inf);
int pos = T.find_0(1, 0, maxn, p + 1);
T.add(1, 0, maxn, p + 1, pos - 1, 0);
inc(pos, 1);
}
}
void dec(int p, int num) {
if (!num) return ;
int tmp = T.ask(1, 0, maxn, p) - num;
if (tmp >= 0) T.add(1, 0, maxn, p, tmp);
else {
T.add(1, 0, maxn, p, tmp + inf + 1);
int pos = T.find_1(1, 0, maxn, p + 1);
T.add(1, 0, maxn, p + 1, pos - 1, inf);
dec(pos, 1);
}
}
void modify(int a, int b) {
int blo = b / base, num = b % base;
if (a > 0) {
inc(blo, (a << num) & inf);
a = a >> base - num;
if (a) inc(blo + 1, a);
} else {
a = -a;
dec(blo, (a << num) & inf);
a = a >> base - num;
if (a) dec(blo + 1, a);
}
}
int query(int k) {
int tmp = T.ask(1, 0, maxn, k / base);
return (tmp & (1 << k % base)) && 1;
}
int main() {
// freopen("integer.in", "r", stdin);
// freopen("integer.out" ,"w", stdout);
scanf("%d%*d%*d%*d", &n);
T.init();
while (n--) {
scanf("%d", &op);
if (op --> 1) {
int k;
scanf("%d", &k);
// printf("%d\n", k);
printf("%d\n", query(k));
// puts("query");
} else {
int a, b;
scanf("%d%d", &a, &b);
if (!a) continue;
modify(a, b);
// puts("modify");
}
}
return 0;
}

  

[NOI2017 D1T1]整数的更多相关文章

  1. LibreOJ2302 - 「NOI2017」整数

    Portal Description 有一个整数\(x=0\),对其进行\(n(n\leq10^6)\)次操作: 给出\(a(|a|\leq10^9),b(b\leq30n)\),将\(x\)加上\( ...

  2. 「NOI2017」整数 解题报告

    「NOI2017」整数 有一些比较简单的\(\log^2n\)做法 比如暴力在动态开点线段树上维护每个位置为\(0\)还是\(1\),我们发现涉及到某一位加上\(1\)或者减去\(1\)实际上对其他位 ...

  3. BZOJ4942【noi2017】整数

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

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

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

  5. noi2017 T1 整数 ——线段树

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

  6. LOJ2302 「NOI2017」整数

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

  7. UOJ#314. 【NOI2017】整数 其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ314.html 题解 如果只加不减,那么瞎势能分析一波可以知道暴力模拟的复杂度是对的. 但是有减法怎么办? ...

  8. LOJ#2302. 「NOI2017」整数

    $n \leq 1000000$个操作:一,给$x$加上$a*2^b$:二,问$x$的某个二进制位$k$.$b,k \leq 30n$,$|a| \leq 1e9$. 30暴露了一切..可以把30个二 ...

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

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

随机推荐

  1. 部署node api的二三事

    当接到node开发node api的时候,我就想用docker来部署,众所周知,node的版本更新迭代很快.很多以前需要babel后才能采用的方法正在不断被node 原生的支持.如果随便更换生产服务器 ...

  2. 【坑】记录一个docker 1.13.1 build 07f3374 版本的坑

    在自家的开发环境中,一般都是直接yum安装最新的docker来做镜像和容器,没有仔细深究,一直相安无事.但这几天却发现一个惊悚的现象,新申请的两台虚机,一台安装好后正常,另一台却出现异常: docke ...

  3. linux wdcp3 上传大文件 服务器i/o错误

    在一次上传大文件时 提示 服务器i/o错误  找了些方法都没有解决 最后发现 wdcp3 面板 默认安装时  web服务器引擎是 nginx + apache 共用 而且 nginx 默认并没与安装  ...

  4. Dynamics 365-下载新版本的开发工具

    可以使用下面的Powershell脚本在NuGet下載最新的CRM开发工具.这些工具包括: Tool NuGet Package Code generation tool CrmSvcUtil.exe ...

  5. 谭浩强第四版第九章课后习题12>>>建立一个链表,每个节点包括:学号、姓名、性别、年龄。输入一个年龄,若链表 中的结点所包含的年龄等于此年龄,则删除此结点。

    #include<stdio.h> #include<stdlib.h> #define N sizeof(link) typedef struct lin { struct ...

  6. c语言中 *p++ 和 (*p)++ 和 *(p++) 和 *(++p) 和++(*p)和 *(p--)和 *(--p)有什么区别?

    *p++是指下一个地址; (*p)++是指将*p所指的数据的值加一; /******************解释**********************/ ->C编译器认为*和++是同优先级 ...

  7. SIMD数据并行(二)——多媒体SIMD扩展指令集

    在计算机体系中,数据并行有两种实现路径:MIMD(Multiple Instruction Multiple Data,多指令流多数据流)和SIMD(Single Instruction Multip ...

  8. CC3200模块的内存地址划分和bootloader(一)

    1. CC3200的内存地址划分非常特殊,如果没测试的话,很容易懵逼.我们先看芯片手册里面的内存地址.芯片的RAM是256KB,下图的0x2000 0000-0x2003 FFFF,正好是256KB. ...

  9. iOS下原生与JS交互(总结)

    iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式. JS调用原生OC篇(我自己用的方式二,简单方便) 方式一 第一种方式是用JS ...

  10. Android 序列化比对

    本文转自:https://www.zybuluo.com/linux1s1s/note/91046 注:部分内容有更改 在Android中使用序列化,无非两种途经: Parcelable 和 Seri ...