传送门

直接把修改的数拆成logloglog个二进制位一个一个修改是会TLETLETLE的。

因此我们把303030个二进制位压成一位储存在线段树里面。

然后维护区间中最靠左二进制位不为0/1的下标。

手动模拟一波进/退位就行了。

代码:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
const int N=2e6+5,up=(1<<30)-1,n=1e6;
struct Node{int l,r,val,cov,pos[2];}T[N<<2];
int q,bit[31];
inline void pushup(int p){T[p].pos[0]=min(T[lc].pos[0],T[rc].pos[0]),T[p].pos[1]=min(T[lc].pos[1],T[rc].pos[1]);}
inline void pushnow(int p,int typ){T[p].cov=typ,T[p].val=typ*up,T[p].pos[typ]=n+1,T[p].pos[typ^1]=T[p].l;}
inline void pushdown(int p){if(~T[p].cov)pushnow(lc,T[p].cov),pushnow(rc,T[p].cov),T[p].cov=-1;}
inline void build(int p,int l,int r){
	T[p].l=l,T[p].r=r,T[p].cov=-1;
	if(T[p].l==T[p].r){T[p].pos[0]=n+1,T[p].pos[1]=l,T[p].val=0;return;}
	build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,int v){
	if(ql>T[p].r||qr<T[p].l)return;
	if(ql<=T[p].l&&T[p].r<=qr)return pushnow(p,v);
	pushdown(p);
	if(qr<=mid)update(lc,ql,qr,v);
	else if(ql>mid)update(rc,ql,qr,v);
	else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
	pushup(p);
}
inline void modify(int p,int k,int v){
	if(T[p].l==T[p].r){T[p].val=v,T[p].pos[0]=T[p].val==0?n+1:T[p].l,T[p].pos[1]=T[p].val==up?n+1:T[p].l;return;}
	pushdown(p);
	if(k<=mid)modify(lc,k,v);
	else modify(rc,k,v);
	pushup(p);
}
inline void change(int p,int k,int v){
	if(T[p].l==T[p].r){T[p].val+=v,T[p].pos[0]=T[p].val==0?n+1:T[p].l,T[p].pos[1]=T[p].val==up?n+1:T[p].l;return;}
	pushdown(p);
	if(k<=mid)change(lc,k,v);
	else change(rc,k,v);
	pushup(p);
}
inline int query(int p,int k){
	if(T[p].l==T[p].r)return T[p].val;
	pushdown(p);
	if(k<=mid)return query(lc,k);
	return query(rc,k);
}
inline int ask(int p,int ql,int qr,int typ){
	if(ql>T[p].r||qr<T[p].l)return n+1;
	if(ql<=T[p].l&&T[p].r<=qr)return T[p].pos[typ];
	pushdown(p);
	if(qr<=mid)return ask(lc,ql,qr,typ);
	if(ql>mid)return ask(rc,ql,qr,typ);
	return min(ask(lc,ql,mid,typ),ask(rc,mid+1,qr,typ));
}
int main(){
	bit[0]=1;
	for(int i=1;i<=30;++i)bit[i]=bit[i-1]<<1;
	build(1,1,n);
	q=read();
	int t=read();
	t=read(),t=read();
	while(q--){
		int op=read();
		if(op==1){
			long long a=read();
			int b=read(),x=b/30+1,y=b%30;
			a=a*bit[y];
			long long upd=1ll*query(1,x+1)*bit[30]+1ll*query(1,x);
			if(a>=0){
				upd+=a;
				modify(1,x,upd%bit[30]),upd/=bit[30];
				modify(1,x+1,upd%bit[30]),upd/=bit[30];
				if(!upd)continue;
				int id=ask(1,x+2,n,1);
				change(1,id,1),update(1,x+2,id-1,0);
			}
			else{
				bool fu=0;
				upd+=a;
				if(upd<0)upd+=1ll*bit[30]*bit[30],fu=1;
				modify(1,x,upd%bit[30]),upd/=bit[30];
				modify(1,x+1,upd%bit[30]),upd/=bit[30];
				if(!fu)continue;
				int id=ask(1,x+2,n,0);
				change(1,id,-1),update(1,x+2,id-1,1);
			}
		}
		else{
			int a=read(),x=a/30+1,y=a%30;
			printf("%d\n",(query(1,x)&bit[y])?1:0);
		}
	}
	return 0;
}

2018.10.30 bzoj4942: [Noi2017]整数(线段树压位)的更多相关文章

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

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

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

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

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

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

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

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

  5. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

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

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

  7. BZOJ4942 NOI2017整数(线段树)

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

  8. noi2017 T1 整数 ——线段树

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

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

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

随机推荐

  1. 160. Intersection of Two Linked Lists (List;Two-Pointers)

    Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...

  2. UVa 1600 Patrol Robot(三维广搜)

    A robot has to patrol around a rectangular area which is in a form of m x n grid (m rows and ncolumn ...

  3. c++笔试题贪吃蛇问题

    贪吃蛇 现在有一个N*M(N,M=100)的方形矩形,在这个矩形的每一个方格上都放有一个随机值,一条可爱的小蛇从矩形的 左上角开始出发,每次移动都只能移动一格,向右或向下,而每到达一格贪吃的小蛇都会吧 ...

  4. .“代理XP”组件已作为此服务器安全配置的一部分被关闭的解决办法

    “代理XP”组件已作为此服务器安全配置的一部分被关闭.系统管理员可以使用sp_configure来启用“代理XP”.有关启用“代理XP”的详细信息,请参阅SQL Server联机丛书中的“外围应用配置 ...

  5. Asp.net Mvc之Action如何传多个参数

    最近,工作上有一个需要:用户查询日志文件信息,查看某一个具体日志信息,可能同时查看该日志所在日期的其他日志信息列表. 为完成此功能,我打算在URL中传入了两个参数,一个记录此日志时间,另外一个记录日志 ...

  6. supervisor 使用教程(转)

    原文地址:https://word.gw1770df.cc/2016-08-04/linux/supervisor-%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/ Supe ...

  7. Selenium + Python + Firefox

    按网上教程搭建好环境后,执行下面的代码出现了错误: 测试代码如下: from selenium import webdriver driver=webdriver.Firefox() driver.g ...

  8. ecplise自动提示失效,使用补全自动提示快捷键(Alt+/),但只显示“No Default Proposals”

    在这里设置了自动提示,但是在使用的时候自动提示实现了.甚至使用补全自动提示快捷键(Alt+/),只显示“No Default Proposals”.今天在网上搜索了一下结果,主要有一下几种方法: 1. ...

  9. [Z]Spring Data JPA 之 一对一,一对多,多对多 关系映射

    一.@OneToOne关系映射 JPA使用@OneToOne来标注一对一的关系. 实体 People :用户. 实体 Address:家庭住址. People 和 Address 是一对一的关系. 这 ...

  10. javascript 重构alert()

    javascript问题,关于重构window.alert()后,然后调用window原本的window.alert()的方法 大神们,问个问题,如果在script标签的第一行散写,重构了window ...