LOJ#2302. 「NOI2017」整数
$n \leq 1000000$个操作:一,给$x$加上$a*2^b$;二,问$x$的某个二进制位$k$。$b,k \leq 30n$,$|a| \leq 1e9$。
30暴露了一切。。可以把30个二进制位压一位,进位用线段树找到第一个0,而退位用类似的方法找到第一个1。
但其实第$k$位只由加的总量和减的总量的0到$k$这些数位上决定。因此可以把加减分成两个数组,不用再写一个线段树里的减法。回答时查一下$0$到$k-1$中加的和减的孰大孰小,以及第$k$位是否相同,分类可得答案。
这里写的直接模拟。
//#include<iostream>
#include<cstring>
#include<cstdio>
//#include<math.h>
//#include<set>
//#include<queue>
//#include<bitset>
//#include<vector>
#include<algorithm>
#include<stdlib.h>
using namespace std; #define LL long long
int qread()
{
char c; int s=,f=; while ((c=getchar())<'' || c>'') (c=='-') && (f=-);
do s=s*+c-''; while ((c=getchar())>='' && c<=''); return s*f;
} //Pay attention to '-' , LL and double of qread!!!! int m,n;
#define maxn 1000011
int pos[maxn];
struct SMT
{
struct Node{int ls,rs,v; bool all0,all1,be0,be1;}a[maxn<<];
int size,n;
void up(int x)
{a[x].all0=a[a[x].ls].all0&a[a[x].rs].all0; a[x].all1=a[a[x].ls].all1&a[a[x].rs].all1;}
void build(int &x,int L,int R)
{
x=++size;
a[x].all0=; a[x].all1=a[x].be0=a[x].be1=;
if (L==R) {a[x].v=; pos[L]=x; return;}
int mid=(L+R)>>;
build(a[x].ls,L,mid); build(a[x].rs,mid+,R);
}
void clear(int N) {n=N; size=; int x; build(x,,n);} void besingle(int x,bool t)
{
a[x].all0=a[x].be0=!t;
a[x].all1=a[x].be1=t;
if (t) a[x].v=(<<)-; else a[x].v=;
}
void down(int x)
{
Node &b=a[x];
if (b.be0) {besingle(b.ls,); besingle(b.rs,); b.be0=;}
if (b.be1) {besingle(b.ls,); besingle(b.rs,); b.be1=;}
} bool Add(int x,int L,int R,int p,int v)
{
if (L==R)
{
a[x].v+=v; if (a[x].v>=(<<))
{
a[x].v^=(<<);
a[x].all0=(a[x].v==),a[x].all1=(a[x].v==(<<)-);
return ;
}
a[x].all0=(a[x].v==),a[x].all1=(a[x].v==(<<)-);
return ;
}
down(x);
int mid=(L+R)>>;
if (p<=mid) {bool flag=Add(a[x].ls,L,mid,p,v); up(x); return flag;}
bool flag=Add(a[x].rs,mid+,R,p,v); up(x); return flag;
}
bool f0(int x,int L,int R,int p)
{
if (L==R)
{
bool flag=;
for (int i=;i<;i++) if (((a[x].v>>i)&)==) {a[x].v|=<<i; flag=; break;}
else a[x].v^=(<<i);
a[x].all0=(a[x].v==),a[x].all1=(a[x].v==(<<)-);
return flag;
}
down(x);
int mid=(L+R)>>;
if (L>p)
{
if (a[x].all1) {besingle(x,); return ;}
if (!f0(a[x].ls,L,mid,p)) f0(a[x].rs,mid+,R,p); up(x);
return ;
}
if (mid>p)
{
if (f0(a[x].ls,L,mid,p)) {up(x); return ;}
bool flag=f0(a[x].rs,mid+,R,p); up(x); return flag;
}
if (f0(a[x].rs,mid+,R,p)) {up(x); return ;}
up(x); return ;
}
void add(int p,int v) {p++; if (Add(,,n,p,v) && p!=n) f0(,,n,p);} bool Minus(int x,int L,int R,int p,int v)
{
if (L==R)
{
a[x].v-=v; if (a[x].v<)
{
a[x].v+=(<<);
a[x].all0=(a[x].v==),a[x].all1=(a[x].v==(<<)-);
return ;
}
a[x].all0=(a[x].v==),a[x].all1=(a[x].v==(<<)-);
return ;
}
down(x);
int mid=(L+R)>>;
if (p<=mid) {bool flag=Minus(a[x].ls,L,mid,p,v); up(x); return flag;}
bool flag=Minus(a[x].rs,mid+,R,p,v); up(x); return flag;
}
bool f1(int x,int L,int R,int p)
{
if (L==R)
{
bool flag=;
for (int i=;i<;i++) if (((a[x].v>>i)&)==) {a[x].v^=<<i; flag=; break;}
else a[x].v^=(<<i);
a[x].all0=(a[x].v==),a[x].all1=(a[x].v==(<<)-);
return flag;
}
down(x);
int mid=(L+R)>>;
if (L>p)
{
if (a[x].all0) {besingle(x,); return ;}
if (!f1(a[x].ls,L,mid,p)) f1(a[x].rs,mid+,R,p);
up(x); return ;
}
if (mid>p)
{
if (f1(a[x].ls,L,mid,p)) {up(x); return ;}
bool flag=f1(a[x].rs,mid+,R,p); up(x); return flag;
}
if (f1(a[x].rs,mid+,R,p)) {up(x); return ;}
up(x); return ;
}
void minus(int p,int v) {p++; if (Minus(,,n,p,v) && p!=n) f1(,,n,p);} int Query(int x,int L,int R,int p,int v)
{
if (L==R) return (a[x].v>>v)&;
down(x);
int mid=(L+R)>>;
if (p<=mid) return Query(a[x].ls,L,mid,p,v);
return Query(a[x].rs,mid+,R,p,v);
}
int query(int x) {return Query(,,n,x/+,x%);}
}t; int main()
{
m=qread(); n=qread(); n=qread(); n=qread();
n=;
t.clear(n); int op,x,y;
while (m--)
{
op=qread();
if (op==)
{
x=qread(); y=qread();
if (x>)
{
int p=y/,q=(p+)*-y;
int a=x&((<<q)-),b=x>>q; a<<=y-p*;
t.add(p,a); if (b) t.add(p+,b);
}
else
{
x=-x;
int p=y/,q=(p+)*-y;
int a=x&((<<q)-),b=x>>q; a<<=y-p*;
t.minus(p,a); if (b) t.minus(p+,b);
}
}
else
{
x=qread();
printf("%d\n",t.query(x));
}
}
return ;
}
LOJ#2302. 「NOI2017」整数的更多相关文章
- LOJ 2302 「NOI2017」整数——压位线段树
题目:https://loj.ac/problem/2302 压30位,a最多落在两个位置上,拆成两次操作. 该位置加了 a 之后,如果要进位或者借位,查询一下连续一段 0 / 1 ,修改掉,再在含有 ...
- LibreOJ2302 - 「NOI2017」整数
Portal Description 有一个整数\(x=0\),对其进行\(n(n\leq10^6)\)次操作: 给出\(a(|a|\leq10^9),b(b\leq30n)\),将\(x\)加上\( ...
- 「NOI2017」整数 解题报告
「NOI2017」整数 有一些比较简单的\(\log^2n\)做法 比如暴力在动态开点线段树上维护每个位置为\(0\)还是\(1\),我们发现涉及到某一位加上\(1\)或者减去\(1\)实际上对其他位 ...
- loj #2305. 「NOI2017」游戏
#2305. 「NOI2017」游戏 题目描述 小 L 计划进行 nnn 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 AAA.BBB. ...
- loj#2305. 「NOI2017」游戏 2-sat
链接 https://loj.ac/problem/2305 https://www.luogu.org/problemnew/show/P3825 思路 3-sat神马的就不要想了,NP问题 除去x ...
- LOJ2302 「NOI2017」整数
「NOI2017」整数 题目背景 在人类智慧的山巅,有着一台字长为$1048576$位(此数字与解题无关)的超级计算机,著名理论计算机科 学家P博士正用它进行各种研究.不幸的是,这天台风切断了电力系统 ...
- LOJ 2304 「NOI2017」泳池——思路+DP+常系数线性齐次递推
题目:https://loj.ac/problem/2304 看了各种题解…… \( dp[i][j] \) 表示有 i 列.第 j 行及以下默认合法,第 j+1 行至少有一个非法格子的概率,满足最大 ...
- LOJ 2303 「NOI2017」蚯蚓排队——链表+哈希表
题目:https://loj.ac/problem/2303 想到合并的时候可以只考虑接口附近的50个,但不太会分析复杂度,而且没有清楚地想到用哈希值对应个数. 看了题解才会…… 一直想用 splay ...
- *LOJ#2306. 「NOI2017」蔬菜
$n \leq 100000$种蔬菜,每个蔬菜有:一单位价格:卖第一单位时额外价格:总量:每天腐烂量.每天能卖$m \leq 10$单位蔬菜,多次询问:前$k \leq 100000$天最多收入多少. ...
随机推荐
- PMD 编译 语法分析 词法分析 抽象语法树
编译原理 163 课堂 http://mooc.study.163.com/learn/-1000002001?tid=1000003000#/learn/content?type=detail&am ...
- 头文件string与string.h的区别
在C++中,#include<iostream>与#include<iostream.h>的区别,前者要使用更新的编译器(其实大部分编译器多比较前卫了,出了有些搞嵌入式的用变态 ...
- 【线性基】bzoj2844: albus就是要第一个出场
线性基求可重rank 题目描述 给定 n 个数 $\{ a_i \}$ ,以及数 $x$. 将 $\{ a_i \}$ 的所有子集(包括空集)的异或值从小到大排序,得到 $\{ b_i \} $. ...
- 【Git版本控制】GitHub上fork项目和clone项目的区别
fork:在github页面,点击fork按钮,将别人的仓库复制一份到自己的仓库. clone:直接将github中的仓库克隆到自己本地电脑中 问题1:pull request的作用 比如在仓库的主人 ...
- PHP计算两个日期相差的年月日时分秒
$start_time = '2017-09-06 15:12:20'; $end_time = '2018-09-08 10:20:45'; get_time($start_time,$end_ti ...
- jenkins+svn+pipeline+kubernetes部署java应用(一)
一.linux安装svn服务端 yum -y install subversion 二.创建svn版本库(项目仓库) mkdir -p /home/svn svnadmin create /home/ ...
- destoon模块自定义字段的添加并让其支持搜索的方法
今天看了看模块设置里的自定义字段功能的用法,试着加了个新字段glry,设置了值,然后去数据库moduleid的article表看,字段成功加上了. 于是去template下article文件夹的lis ...
- Python入门基本语法
Python入门 以下主要讲述Python的一些基础语法,包含行的缩进在python中的重要意义,python中常见的保留字和引号的使用,如何实现单行注释和多行注释. print("he ...
- List删除元素
在单线程环境下的解决办法 public void remove() { if (lastRet == -1) throw new IllegalStateException(); checkForCo ...
- zoj 4054
#define ll long long ; int t; ll ans,tmp; char s[N]; int main() { scanf("%d",&t); whil ...