[bzoj4942] [洛谷P3822] [NOI2017] 整数
题目链接##
https://www.luogu.org/problemnew/show/P3822
想法##
这个啊,就是线段树哇
最初的想法是每位一个节点,然后进位、退位找这一位前面第一个0或第一个1,然后把中间一段修改了即可
但是每位一个节点太浪费了,会超时,故可以压位,30位一个节点
要找每个点前面第一个0或1的话,可以记录一下每个区间里是否全0或全1,不停地维护
反正基本思路就是这样,但是代码真心挺恶心的,调了一天呢!NOI题真是毒瘤!
(初三一模前两天调这个代码,酸爽啊……qwq)
代码##
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int read(){
char ch=getchar();
int ret=0,f=1;
while(!isdigit(ch) && ch!='-') ch=getchar();
if(ch=='-') f=-1,ch=getchar();
while(isdigit(ch)) ret=ret*10+ch-'0',ch=getchar();
return f*ret;
}
typedef long long ll;
const int N = 1000005;
const int MAX = 1000000;
const int FULL = (1<<30)-1;
struct node{
int v,flag,lazy,id;
node *ch[2],*pa;
}pool[N*4],*root;
int cnt;
void build(node *p,int l,int r){
p->v=p->flag=0; p->lazy=-1;
if(l==r) { p->id=l; return; }
int mid=(l+r)>>1;
build(p->ch[0]=&pool[++cnt],l,mid);
build(p->ch[1]=&pool[++cnt],mid+1,r);
p->ch[0]->pa=p; p->ch[1]->pa=p;
}
void update(node *p){
if(!p->ch[0]){ //single
if(p->v==FULL) p->flag=1;
else if(p->v==0) p->flag=0;
else p->flag=-1;
}
else if(p->ch[0]->flag==p->ch[1]->flag) p->flag=p->ch[0]->flag;
else p->flag=-1;
}
void up(node *p){
if(!p) return;
update(p); up(p->pa);
}
void pushdown(node *p){
if(p->lazy==-1) return;
if(!p->ch[0]) return;
p->ch[0]->lazy=p->lazy; p->ch[0]->flag=p->lazy;
if(!p->ch[0]->ch[0]) p->ch[0]->v=p->lazy ? FULL : 0;
p->ch[1]->lazy=p->lazy; p->ch[1]->flag=p->lazy;
if(!p->ch[1]->ch[0]) p->ch[1]->v=p->lazy ? FULL : 0;
p->lazy=-1;
}
node *get_node(node *p,int l,int r,int c){
if(l==r) return p;
pushdown(p);
int mid=(l+r)>>1;
if(c<=mid) return get_node(p->ch[0],l,mid,c);
return get_node(p->ch[1],mid+1,r,c);
}
void fix(node *p,int l,int r,int c,int f){
if(l==r){
if(f==0) p->v++;
else p->v--;
update(p);
return;
}
pushdown(p);
int mid=(l+r)>>1;
if(c<=mid) fix(p->ch[0],l,mid,c,f);
else fix(p->ch[1],mid+1,r,c,f);
update(p);
}
void change(node *p,int l,int r,int L,int R,int f){
if(l==L && r==R){
p->lazy=p->flag=f;
if(l==r) p->v= f ? FULL : 0;
return;
}
pushdown(p);
int mid=(l+r)>>1;
if(R<=mid) change(p->ch[0],l,mid,L,R,f);
else if(L>mid) change(p->ch[1],mid+1,r,L,R,f);
else{
change(p->ch[0],l,mid,L,mid,f);
change(p->ch[1],mid+1,r,mid+1,R,f);
}
update(p);
}
int find(node *p,int c,int f){ //f=1: 011111 f=0:100000
if(p->flag!=f){
if(!p->ch[0]) return p->id;
if(c==-1){
pushdown(p);
if(p->ch[0]->flag!=f) return find(p->ch[0],-1,f);
else return find(p->ch[1],-1,f);
}
if(c==0 && p->ch[1] && p->ch[1]->flag!=f) return find(p->ch[1],-1,f);
return find(p->pa,p==p->pa->ch[1],f);
}
return find(p->pa,p==p->pa->ch[1],f);
}
void add(int a,int x){
int ty=a/30+1,y=x*(1<<(a-(ty-1)*30));
node *p=get_node(root,1,MAX,ty);
if(p->v+y<=FULL) { p->v+=y; up(p); return; }
p->v=p->v+y-FULL-1; up(p);
node *q=get_node(root,1,MAX,ty+1);
int v=find(q,0,1);
if(v==ty+1) fix(root,1,MAX,ty+1,0);
else change(root,1,MAX,ty+1,v-1,0),fix(root,1,MAX,v,0);
}
void del(int a,int x){
int ty=a/30+1,y=x*(1<<(a-(ty-1)*30));
node *p=get_node(root,1,MAX,ty);
if(p->v-y>=0) { p->v-=y; up(p); return; }
p->v=p->v-y+FULL+1; up(p);
node *q=get_node(root,1,MAX,ty+1);
int v=find(q,0,0);
if(v==ty+1) fix(root,1,MAX,ty+1,1);
else change(root,1,MAX,ty+1,v-1,1),fix(root,1,MAX,v,1);
}
void Add(int a,int x){
int ty=a/30+1;
ll y=x*(1ll<<(a-(ty-1)*30));
if(y<=1ll*FULL) add(a,x);
else add((ty-1)*30,(int)(y%(FULL+1))),add(ty*30,(int)(y/(FULL+1)));
}
void Del(int a,int x){
int ty=a/30+1;
ll y=x*(1ll<<(a-(ty-1)*30));
if(y<=1ll*FULL) del(a,x);
else del((ty-1)*30,(int)(y%(FULL+1))),del(ty*30,(int)(y/(FULL+1)));
}
int main()
{
int n,opt,a,b;
n=read();read();read();read();
root=&pool[++cnt];
build(root,1,MAX);
for(int i=0;i<n;i++){
opt=read();
if(opt==1){
a=read(); b=read();
if(a>0) Add(b,a);
else if(a<0) Del(b,-a);
}
else{
a=read();
node *p=get_node(root,1,MAX,a/30+1);
printf("%d\n",(p->v&(1<<(a-(a/30)*30)))!=0 ? 1 : 0);
}
}
return 0;
}
[bzoj4942] [洛谷P3822] [NOI2017] 整数的更多相关文章
- 洛谷3822 [NOI2017] 整数 【线段树】【位运算】
题目分析: 首先这题的询问和位(bit)有关,不难想到是用线段树维护位运算. 现在我们压32位再来看这道题. 对于一个加法操作,它的添加位置可以得到,剩下的就是做不超过32的位移.这样根据压位的理论. ...
- 洛谷3825 [NOI2017]游戏 2-sat
原文链接http://www.cnblogs.com/zhouzhendong/p/8146041.html 题目传送门 - 洛谷3825 题解 我们考虑到地图中x的个数很少,最多只有8个. 所以我们 ...
- 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】
题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...
- 洛谷 P3825 [NOI2017]游戏 【2-SAT+状压】
UOJ和洛谷上能A,bzoj 8ms即WA,现在也不是知道为啥--因为我太弱了 先看数据范围发现d非常小,自然想到了状压. 所以先假装都是只能跑两种车的,这显然就是个2-SAT问题了:对于x场没有hx ...
- 洛谷——P1107 最大整数
P1107 最大整数 题目描述 设有n个正整数 (n<=20), 将它们连接成一排, 组成一个最大的多位整数. 例如: n=3时, 3个整数13, 312, 343连接成的最大整数为: 3433 ...
- codevs——T1860 最大数||洛谷——P1107 最大整数
http://codevs.cn/problem/1860/ || https://www.luogu.org/problem/show?pid=1107#sub 题目描述 Description 设 ...
- 洛谷——P1151 子数整数
P1151 子数整数 题目描述 对于一个五位数a1a2a3a4a5,可将其拆分为三个子数: sub1=a1a2a3 sub2=a2a3a4 sub3=a3a4a5 例如,五位数20207可以拆分成 s ...
- 洛谷3823 [NOI2017] 蚯蚓排队 【哈希】
题目分析: 从$\sum|S|$入手.共考虑$\sum|S|$个$f(t)$.所以我们要一个对于每个$f(t)$在$O(1)$求解的算法.不难想到是哈希. 然后考虑分裂和合并操作.一次合并操作要考虑合 ...
- 洛谷P3825 [NOI2017]游戏(2-SAT)
传送门 果然图论的题永远建图最麻烦……看着题解代码的建图过程真的很珂怕…… 先不考虑地图$x$,那么每一个地图都只能用两种赛车,于是我们可以用2-SAT来搞,用$i$表示这个地图能用的第一辆车,$i' ...
随机推荐
- Pandas处理缺失数据
利用pandas.DataFrame.dropna处理含有缺失值的数据 1.使用形式: DataFrame.dropna(axis=0, how='any', thresh=None, subset= ...
- hibernate 大对象类型的hibernate映射
在 Java 中, java.lang.String 可用于表示长字符串(长度超过 255), 字节数组 byte[] 可用于存放图片或文件的二进制数据. 此外, 在 JDBC API 中还提供了 j ...
- 16python的map函数,filter函数,reduce函数
map num_l = [1,6,8,9] def map_test(func,array): ret = [] for i in array: res = func(i) ret.append(re ...
- 9.python入门
借鉴:https://www.cnblogs.com/wupeiqi/articles/5433925.html 一.HelloWorld print("HelloWorld") ...
- 王雅超的学习笔记-大数据hadoop集群部署(十)
Spark集群安装部署
- 算法复杂度之 空间复杂度(Java)
0.说明 根据算法书上的定义,一个算法的空间复杂度包括算法程序所占用的空间,输入初始数据所占用的空间以及算法执行过程中所需要的额外空间.本文各种结论全部参考过标准文献,本人也进行过验证.验证过程本文不 ...
- 【题解】Killer Names($O(n\log n)$做法)
[题解]Killer Names(\(O(n\log n)\)做法) HDU - 6143 感觉好久没做过这种直来直去的组合题,过来水一篇题解.还以为要写一个\(MTT\)或者三模数\(NTT\),想 ...
- 洛谷$1541$ 乌龟棋 线性$DP$
Luogu CH Sol f[i]表示走到第i个格子时获得的最大分数 发现转移与各个爬行卡片的数量有关,一共只有4种卡片 所以就把这四种卡片的已使用张数也放进状态,f[i][a][b][c][d] ...
- Java集合使用之next方法与remove方法 | Java集合使用之remove方法使用易错
Iterator接口的remove方法将会删除上次调用next方法时返回的元素. next方法和remove方法的调用具有相互依赖性,如果调用remove方法前没有调用next方法是不合法的. 错误使 ...
- 子网划分及NAT技术总结
近段项目需要用到网络相关的知识,硬着头皮又回顾了一波,这里做一下记录. 一 分类的IP地址 我们使用的IP地址(IP V4)可以划分为A,B,C,D,E 5个类型,其中的D,为组播地址,E类地址为保留 ...