BZOJ4942【noi2017】整数

时间:2023-03-08 16:49:00

luogu的题面

https://www.luogu.org/problemnew/show/P3822

题意:
     x初始为0,维护+a*2^k ,其中a为整数,k为自然数;查询x的第k位;

题解:
    ①将数看成序列,线段树逐位维护。比较大,压位(下面的代码base=30,ls()
rs()为左右儿子)。

    ②输入1,a,b,即将b/base号节点加 (a<<b%base)的base位以内部分,b/base+1号节点加 (a<<b%base)base位以上的部分。

    ③假设我们已经找到了b对应的叶子节点,修改后考虑进位。定义fg1[k]表示k节点是否是最大值(1<<base)-1,b对应的叶子往上跳一层到k号节点,如果fg1[rs(k)]==false,直接rs(k)里进位就好了,否则把rs(k)清零,再往上跳,退位同理(写的时候记得pushdown和pushup 。。。。TAT);

 #pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
//#define N 1000100
//#define base 30
#define ll long long
#define ls(k) (k<<1)
#define rs(k) (ls(k)|1)
using namespace std;
const ll base=,N=4.2e7/base,B=(<<base)-,len=4.1e7/base;
//const int B = (1<<base) - 1,len = 1e6 + 5;
int n,t1,t2,t3;
int w[N<<],fg1[N<<],fg0[N<<],ly1[N<<],ly0[N<<];
char gc(){
static char *p1,*p2,s[];
if(p1==p2) p2=(p1=s)+fread(s,,,stdin);
return(p1==p2)?EOF:*p1++;
}
int rd(){
int x = ,f = ; char c = gc();
while(c<''||c>'') {if(c=='-') f = -; c = gc();}
while(c>=''&&c<='') {x = x * + c - ''; c = gc();}
return x * f;
}
void pushup(int k){
int l = ls(k),r = rs(k);
fg0[k] = fg0[l] && fg0[r];
fg1[k] = fg1[l] && fg1[r];
}
void mdf(int k,int typ){
w[k] = B * typ;
fg1[k] = ly1[k] = typ;
fg0[k] = ly0[k] = !typ;
}
void pushdown(int k){
int l = ls(k),r = rs(k);
if(ly0[k]) mdf(l,),mdf(r,),ly0[k] = ;
if(ly1[k]) mdf(l,),mdf(r,),ly1[k] = ;
}
void change(int k,int l,int r,int typ){
if(l==r) {
w[k]+=typ;
fg0[k] = !w[k];
fg1[k] = (w[k]==B);
}
else{
if(ly0[k]||ly1[k]) pushdown(k);
int mid = (l+r)>>;
if(typ==){
if(!fg1[ls(k)]) change(ls(k),l,mid,);
else mdf(ls(k),),change(rs(k),mid+,r,);
}
else{
if(!fg0[ls(k)]) change(ls(k),l,mid,-);
else mdf(ls(k),),change(rs(k),mid+,r,-);
}
pushup(k);
}
}
int update(int k,int l,int r,int x,int y){
if(!y) return ;
int typ = ;
if(l==r) {
w[k] += y;
if(w[k]>=(<<base)) w[k] -= (<<base),typ = ;
else if(w[k]<) w[k] += (<<base),typ = -;
fg0[k] = !w[k];
fg1[k] = (w[k]==B);
}
else {
if(ly0[k]||ly1[k]) pushdown(k);
int mid = (l + r)>>;
if(x<=mid){
typ = update(ls(k),l,mid,x,y);
if(typ==) {
if(!fg1[rs(k)]) typ = ,change(rs(k),mid+,r,);
else mdf(rs(k),);
}
if(typ==-){
if(!fg0[rs(k)]) typ = ,change(rs(k),mid+,r,-);
else mdf(rs(k),);
}
}
else typ = update(rs(k),mid+,r,x,y);
pushup(k);
}
return typ;
}
int query(int k,int l,int r,int x,int y){
if(l==r) return bool(w[k]&y);
else {
if(ly0[k]||ly1[k]) pushdown(k);
int mid = (l + r)>>;
if(x<=mid) return query(ls(k),l,mid,x,y);
else return query(rs(k),mid+,r,x,y);
}
}
int main()
{ //freopen("mzoj1111.in","r",stdin);
//freopen("mzoj1111.out","w",stdout);
n = rd(); t1 = rd(); t2 = rd(); t3 = rd();
fg0[] = ly0[] = ;
for(int i = ;i <= n;i++){
ll opt = rd(),f,a,b,x,y;
if(opt&){
a = rd(); b = rd();
if(a<) a*=-,f=-; else f=;
a <<= (b%base); b /= base;
update(,,len,b,f*(a&B));
update(,,len,b+,f*(a>>base));
}
else{
x = rd();
y = <<(x%base); x /= base;
int ans = query(,,len,x,y);
printf("%d\n",ans);
}
}
return ;
}//by tkys_Austin;