BZOJ4942 & UOJ314:[NOI2017]整数——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=4942

http://uoj.ac/problem/314

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

题面是markdown形式的所以我传不上……

UPD:18.5.11改成对参考代码的理解失误。

参考:http://www.cnblogs.com/RabbitHu/p/UOJ314.html仔细思考之后发现lazy标记可以不下传,因为区间修改都是改0/INF,单点修改就直接改就行了……

(晚上睡前突然发现这个sb问题然后太晚了只好现在改。)

暴力修改显然是不行的。

考虑让你改的是a*2^b,已经明示了想让你直接修改二进制位,于是把a用O(log)时间拆成二进制然后log次加减,期间的进位退位问题用参考博客的方法可以O(log)实现。

但问题是位数一共有3e7……显然会T的。

于是压60位,这样时间复杂度就有保证了。

(我记得以前有人批评松松松就是因为他WC出神题然后NOI出签到题……woc我怕不是送分题都做不出来我退役吧。)

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+5;
const int B=60;
const ll INF=(1LL<<B)-1;
inline ll read(){
    ll X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
ll lazy[N*4+100],val[N*4+100];
int pos[N*4+100];
bool tag[N*4+10][2];
inline void upt(int a){
    tag[a][0]=tag[a<<1][0]&tag[a<<1|1][0];
    tag[a][1]=tag[a<<1][1]&tag[a<<1|1][1];
}
inline void mdy(int a,ll x){
    if(pos[a]!=-1)val[pos[a]]=x;
    if(x==0)tag[a][0]=1,tag[a][1]=0;
    else if(x==INF)tag[a][0]=0,tag[a][1]=1;
    else tag[a][0]=tag[a][1]=0;
    lazy[a]=x;
}
inline void push(int a){
    if(lazy[a]==-1)return;
    mdy(a<<1,lazy[a]);
    mdy(a<<1|1,lazy[a]);
    lazy[a]=-1;
}
void build(int a,int l,int r){
    tag[a][0]=1;lazy[a]=-1;pos[a]=-1;
    if(l==r){
        pos[a]=l;
        return;
    }
    int mid=(l+r)>>1;
    build(a<<1,l,mid);build(a<<1|1,mid+1,r);
}
void modify(int a,int l,int r,int l1,int r1,ll x){
    if(r<l1||r1<l||l1>r1)return;
    if(l1<=l&&r<=r1){
        mdy(a,x);
        return;
    }
    push(a);
    int mid=(l+r)>>1;
    modify(a<<1,l,mid,l1,r1,x);
    modify(a<<1|1,mid+1,r,l1,r1,x);
    upt(a);
}
ll query(int a,int l,int r,int p){
    if(l==r)return val[l];
    push(a);
    int mid=(l+r)>>1;
    if(p<=mid)return query(a<<1,l,mid,p);
    else return query(a<<1|1,mid+1,r,p);
}
int find(int a,int l,int r,int p,int o){
    if(tag[a][!o])return -1;
    if(l==r)return l;
    push(a);
    int mid=(l+r)>>1,tmp;
    if(p<=mid&&(tmp=find(a<<1,l,mid,p,o))!=-1)return tmp;
    return find(a<<1|1,mid+1,r,p,o);
}
void add(int p,ll x){
    ll tmp=query(1,0,N,p);
    modify(1,0,N,p,p,(tmp+x)&INF);
    if(tmp+x>INF){
        int r=find(1,0,N,p+1,0);
        modify(1,0,N,r,r,val[r]+1);
        modify(1,0,N,p+1,r-1,0);
    }
}
void del(int p,ll x){
    ll tmp=query(1,0,N,p);
    modify(1,0,N,p,p,(tmp-x)&INF);
    if(tmp-x<0){
        int r=find(1,0,N,p+1,1);
        modify(1,0,N,r,r,val[r]-1);
        modify(1,0,N,p+1,r-1,INF);
    }
}
int main(){
    int n=read();read(),read(),read();
    build(1,0,N);
    for(int i=1;i<=n;i++){
        int op=read();
        if(op==1){
            ll a=read(),b=read();
            ll p=b/B,m=b%B;
            if(a>0){
                ll x=(ll)a<<m&INF;
                if(x)add(p,x);
                p++;a>>=(B-m);
                if(a)add(p,a);
            }else{
                a=-a;
                ll x=(ll)a<<m&INF;
                if(x)del(p,x);
                p++;a>>=(B-m);
                if(a)del(p,a);
            }
        }else{
            ll k=read();
            printf("%lld\n",query(1,0,N,k/B)>>(k%B)&1);
        }
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2018-05-10 21:04  luyouqi233  阅读(189)  评论(0编辑  收藏  举报