luogu3822 [NOI2017] Integer

[NOI2017] integer

The simplest idea is to simulate the process, i.e. for the \ (A \) which is split into a number of \ (2 ^ i \) a sum, and then each of violence on the precision binary number to plus or minus, for addition, we add 1 on this one, if this one turns out to be, then we will be high at 1 on a continuous period of 1 to a 0, and the next bit Jiangzai 0 to 1 (simulate what carry this process ). Similarly subtraction, then, it is to swap the 01 above

In this case time complexity is \ (O (nlog ^ 2n) \) , will be card

Obviously every thing is on only \ (0 \) too wasteful, we can consider a continuous \ (30 \) binary bits are pressed together, so without considering most of the time only carry two modifications, considering the carry bit words need only consider the continuous high \ (0 \) or \ (2 ^ {30} -1 \) to

Time is optimized to \ (O (nlogn) \) can be, whether the query section is a continuous \ (0 \) or \ (2 ^ {30} -1 \) can maintain a section through the segment tree \ (or / and \ ) and to query

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
const int N=1000010,M=(1<<30)-1,B=30;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
struct node{
    int suma,sumo;
}seg[4004000];
int n,tag[4004000];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

void pushup(int id)
{
    //cout <<seg[id<<1].sumo << " " << seg[id<<1].suma << " " << seg[id<<1|1].sumo << " " << seg[id<<1|1].suma << endl;
    seg[id].sumo=(seg[id<<1].sumo|seg[id<<1|1].sumo);
    seg[id].suma=(seg[id<<1].suma&seg[id<<1|1].suma);
}

void pushdown(int id)
{
    if (tag[id]!=-1)
    {
        seg[id<<1].sumo=seg[id<<1].suma=tag[id<<1]=seg[id<<1|1].sumo=seg[id<<1|1].suma=tag[id<<1|1]=tag[id];
        tag[id]=-1;
    }
}

int find0(int id,int l,int r,int pos)
{
    if (seg[id].suma==M) return -1;
    if (l==r) return l;pushdown(id);
    int mid=(l+r)>>1,ans=-1;
    if (pos<=mid) ans=find0(id<<1,l,mid,pos);
    if (ans!=-1) return ans;
    else return find0(id<<1|1,mid+1,r,pos);
}

int find1(int id,int l,int r,int pos)
{
    if (seg[id].sumo==0) return -1;
    if (l==r) return l;pushdown(id);
    int mid=(l+r)>>1,ans=-1;
    if (pos<=mid) ans=find1(id<<1,l,mid,pos);
    if (ans!=-1) return ans;
    else return find1(id<<1|1,mid+1,r,pos);
}

void modify(int id,int l,int r,int ql,int qr,int val)
{
    //cout << id << " "<< l << " " << r << " " << ql << " " << qr << endl;
    if ((l>=ql) && (r<=qr)) 
    {
        seg[id].sumo=val;seg[id].suma=val;tag[id]=val;
        return;
    }
    int mid=(l+r)>>1;pushdown(id);
    if (ql<=mid) modify(id<<1,l,mid,ql,qr,val);
    if (qr>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
    pushup(id);
}

void update(int id,int l,int r,int pos,int val)
{
    //cout << l << " " << r << " "  << pos << " " << seg[id].suma << endl;
    if (l==r) {seg[id].sumo+=val;seg[id].suma+=val;return;}
    int mid=(l+r)>>1;pushdown(id);
    if (pos<=mid) update(id<<1,l,mid,pos,val);
    else update(id<<1|1,mid+1,r,pos,val);
    pushup(id);
}

int query(int id,int l,int r,int pos)
{
    if (l==r) return seg[id].sumo;
    int mid=(l+r)>>1;pushdown(id);
    if (pos<=mid) return query(id<<1,l,mid,pos);
    else return query(id<<1|1,mid+1,r,pos);
}

void inc(int pos,int val)
{
    int now=query(1,0,N,pos);
    if (now+val<=M) update(1,0,N,pos,val);
    else
    {
        update(1,0,N,pos,val-(M+1));
        int nxt=find0(1,0,N,pos+1);
        if (nxt>pos+1) modify(1,0,N,pos+1,nxt-1,0);
        update(1,0,N,nxt,1);
    }
}

void dec(int pos,int val)
{
    int now=query(1,0,N,pos);
    if (now>=val) update(1,0,N,pos,-val);
    else
    {
        update(1,0,N,pos,(M+1)-val);
        int nxt=find1(1,0,N,pos+1);
        if (nxt>pos+1) modify(1,0,N,pos+1,nxt-1,M);
        update(1,0,N,nxt,-1);
    }
}

void build(int id,int l,int r)
{
    tag[id]=-1;
    if (l==r) return;
    int mid=(l+r)>>1;
    build(id<<1,l,mid);build(id<<1|1,mid+1,r);
}

int main()
{
    //freopen("a.out","w",stdout);
    n=read();read();read();read();
    build(1,0,N);
    rep(i,1,n)
    {
        int op=read();
        if (op==1)
        {
            int a=read(),b=read(),wei=b/B;
            if (a>0)
            {
                inc(wei,(a<<(b-wei*B))&M);
                inc(wei+1,(a>>((wei+1)*B-b)));
            }
            else
            {
                a=-a;
                dec(wei,(a<<(b-wei*B))&M);
                dec(wei+1,(a>>((wei+1)*B-b)));
            }
        }
        else if (op==2)
        {
            int x=read(),wei=x/B;
            int ans=query(1,0,N,wei);
            int rst=x-wei*B;
            printf("%d\n",(ans>>rst)&1);
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/encodetalker/p/11141331.html