题目链接##

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] 整数的更多相关文章

  1. 洛谷3822 [NOI2017] 整数 【线段树】【位运算】

    题目分析: 首先这题的询问和位(bit)有关,不难想到是用线段树维护位运算. 现在我们压32位再来看这道题. 对于一个加法操作,它的添加位置可以得到,剩下的就是做不超过32的位移.这样根据压位的理论. ...

  2. 洛谷3825 [NOI2017]游戏 2-sat

    原文链接http://www.cnblogs.com/zhouzhendong/p/8146041.html 题目传送门 - 洛谷3825 题解 我们考虑到地图中x的个数很少,最多只有8个. 所以我们 ...

  3. 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】

    题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...

  4. 洛谷 P3825 [NOI2017]游戏 【2-SAT+状压】

    UOJ和洛谷上能A,bzoj 8ms即WA,现在也不是知道为啥--因为我太弱了 先看数据范围发现d非常小,自然想到了状压. 所以先假装都是只能跑两种车的,这显然就是个2-SAT问题了:对于x场没有hx ...

  5. 洛谷——P1107 最大整数

    P1107 最大整数 题目描述 设有n个正整数 (n<=20), 将它们连接成一排, 组成一个最大的多位整数. 例如: n=3时, 3个整数13, 312, 343连接成的最大整数为: 3433 ...

  6. codevs——T1860 最大数||洛谷——P1107 最大整数

    http://codevs.cn/problem/1860/ || https://www.luogu.org/problem/show?pid=1107#sub 题目描述 Description 设 ...

  7. 洛谷——P1151 子数整数

    P1151 子数整数 题目描述 对于一个五位数a1a2a3a4a5,可将其拆分为三个子数: sub1=a1a2a3 sub2=a2a3a4 sub3=a3a4a5 例如,五位数20207可以拆分成 s ...

  8. 洛谷3823 [NOI2017] 蚯蚓排队 【哈希】

    题目分析: 从$\sum|S|$入手.共考虑$\sum|S|$个$f(t)$.所以我们要一个对于每个$f(t)$在$O(1)$求解的算法.不难想到是哈希. 然后考虑分裂和合并操作.一次合并操作要考虑合 ...

  9. 洛谷P3825 [NOI2017]游戏(2-SAT)

    传送门 果然图论的题永远建图最麻烦……看着题解代码的建图过程真的很珂怕…… 先不考虑地图$x$,那么每一个地图都只能用两种赛车,于是我们可以用2-SAT来搞,用$i$表示这个地图能用的第一辆车,$i' ...

随机推荐

  1. 原生js添加鼠标事件的兼容性写法

    兼容pc和移动端,还兼容了surface平板. surface平板特别坑,既可以用鼠标也能用触摸屏,也就是说同时有touch事件和mouse事件. function addEvent(_target, ...

  2. 算法提高 密码锁 (BFS)

    问题描述 你获得了一个据说是古代玛雅人制作的箱子.你非常想打开箱子看看里面有什么东西,但是不幸的是,正如所有故事里一样,神秘的箱子出现的时候总是会挂着神秘的锁. 这个锁上面看起来有  N  个数字,它 ...

  3. H3C配置设备的FTP服务

  4. TOJ5705动态序列操作(STL or treap)

    传送门:动态序列操作 在一个动态变化的序列中,完成以下基本操作: (1)插入一个整数 (2)删除一个整数 (3)查找序列中最大的数 (4)查找序列中最小的数 (5)求x的前驱(前驱定义为不大于x的序列 ...

  5. Nodejs之使用express框架搭建WEB应用

      首先创建一个index.js,在里面引入相关的中间件,如果没有这些中间件,则需要在nodejs里进入index.js所在的文件夹安装这些模块,安装命令:npm install express ex ...

  6. codeforces 1217E E. Sum Queries? (线段树

    codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...

  7. codeforces 1183F 离散化枚举 约数定理

    codeforces1183F 有技巧的暴力 传送门:https://codeforces.com/contest/1183/problem/F 题意: 给你n个数,要你从中选出最多三个数,使得三个数 ...

  8. C. 【UNR #3】配对树

    题解: 首先可以贪心 于是问题可以等价成一条边被算当且仅当子树中个数为奇数个 题解的做法比较简单 考虑每条边,加入其子树内的点 然后为了保证区间长度为偶数 分成f0,0 f0,1 f1,0 f1,1即 ...

  9. Python上下文管理使用

    import contextlib from queue import Queue @contextlib.contextmanager def myOpen(file): f = open(file ...

  10. UITapGestureRecognizer 和 UICollectionView、UITableView的点击事件冲突问题

    解决:https://blog.gocy.tech/2016/11/19/iOS-touch-handling/ 1. tap.delegate = self; tap加个代理<UIGestur ...