NOI2017整数

Posted BLMontgomery

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOI2017整数相关的知识,希望对你有一定的参考价值。

原题链接

发现进位或退位时,会有连续的一段1变成0或连续的0变成1,然后在后面产生一个进位或退位。于是我们只需要一颗线段树支持区间赋值,查询左边第一个1/0,以及单点查询值。可以把a按二进制拆开去修改,复杂度是O(nlognloga)的,这样好像过不去。

于是我的做法是在线段树的每个叶子节点存32位,用unsigned int保存,修改时就只需将a拆成跨过叶子节点的两部分分开进行修改即可,复杂度O(nlogn)。

查询左边第一个0/1时,可以维护每个区间是全为1/全为0/又有0又有1。

我的线段树好像十分丑,看看思想就行了吧。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
inline void read(int &re)
{
    char ch=getchar();int g=1;
    while(ch<0||ch>9) {if(ch==-)g=-1;ch=getchar();}
    re=0;
    while(ch<=9&&ch>=0) re=(re<<1)+(re<<3)+ch-48,ch=getchar();
    re*=g;
}
typedef long long ll;
typedef double db;
typedef unsigned int ui;
const int inf=0x3f3f3f3f;
const int N=2000050;
const ui be[3]={0,(((1u<<31)-1u)<<1)+1u};
const ui bas=201351523u;
int c,d,h,x,y,ss,in,ans=0,othc,jin,kep;
ui a[(N<<2)+1];
int blo[N*30+1];
int tag[(N<<2)+1];

inline void pushdown(int o,int r,int l)
{
    if(l!=r&&tag[o])
    {
        tag[o<<1]=tag[o];tag[o<<1|1]=tag[o];
        a[o<<1]=be[tag[o]&1];a[o<<1|1]=be[tag[o]&1];
    }
    tag[o]=0;
}

inline void maintain(int o)
{
    if(a[o<<1]==be[0]) a[o]=be[0];
    else if(a[o<<1]==be[1]) a[o]=be[1];
    else {a[o]=bas;return ;}
    if((a[o<<1|1]!=be[0]&&a[o<<1|1]!=be[1])||a[o<<1|1]!=a[o]) {a[o]=bas;return ;}
}

void update(int o,int r,int l,int k)
{
    if(x<=l&&r<=y)
    {
        tag[o]=k;
        a[o]=be[k&1];
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(x<=mid) update(o<<1|1,mid,l,k);
    if(y>mid) update(o<<1,r,mid+1,k);
    maintain(o);
}

void always(int o,int r,int l,int k)
{
    if(l==r)
    {
        for(int i=0;i<=31;++i) if(((a[o]>>i)&1u)==k) 
        {
            a[o]^=(1<<i);
            for(int j=0;j<i;++j) a[o]^=(1<<j);
            break;
        }
        y=l-1;
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(a[o<<1|1]!=be[!k]) always(o<<1|1,mid,l,k);
    else always(o<<1,r,mid+1,k);
    maintain(o);
}

void go(int o,int r,int l,int k)
{
    if(!kep) return ;
    if(x<=l&&r<=y)
    {
        if(a[o]!=be[!k]) always(o,r,l,k),kep=0;
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(x<=mid) go(o<<1|1,mid,l,k);
    if(y>mid) go(o<<1,r,mid+1,k);
    maintain(o);
}

void find(int o,int r,int l,int k)
{
    if(blo[x]<=l&&r<=blo[y])
    {
        if(!k)
        {
            ui rest=be[1]-a[o];
            if(rest>=c) a[o]+=c;
            else jin=1,a[o]+=c;
        }
        else
        {
            if(a[o]>=c) a[o]-=c;
            else jin=1,a[o]-=c;
        }
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(blo[x]<=mid) find(o<<1|1,mid,l,k);
    if(blo[y]>mid) find(o<<1,r,mid+1,k);
    maintain(o);
}

int query(int o,int r,int l,int k)
{
    if(x<=l&&r<=y) return (a[o]>>(k%32))&1;
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(x<=mid) return query(o<<1|1,mid,l,k);
    if(y>mid) return query(o<<1,r,mid+1,k);
    maintain(o);
}

int main()
{
    int i,j,opt,T;
    read(T);read(i);read(i);read(i);
    h=log2(30.0*T)+0.999999999;
    int st=1<<h;
    for(i=0;i<st;++i) blo[i]=(i>>5)+1;
    h=log2(T)+0.999999999;
    
    while(T--)
    {
        read(opt);
        if(opt==1)
        {
            read(c);read(d);
            if(!c) continue;
            ui ago=c;int agod=d;
            jin=0;kep=1;
            if(c>0)
            {
                x=d;y=d;
                c<<=(d%32);
                if(c) find(1,1<<h,1,0);//tail
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,0);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,2);
                }
                
                jin=0;kep=1;
                if(!(d%32)) continue;
                c=ago>>(32-d%32);d=d-d%32+32;//head
                x=d;y=d;
                if(c) find(1,1<<h,1,0);
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,0);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,2);
                }
            }
            else
            {
                c=abs(c);ago=c;
                x=d;y=d;
                c<<=(d%32);
                if(c) find(1,1<<h,1,1);
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,1);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,1);
                }
                
                jin=0;kep=1;
                if(!(d%32)) continue;
                c=ago>>(32-d%32);d=d-d%32+32;
                x=d;y=d;
                if(c) find(1,1<<h,1,1);
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,1);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,1);
                }
            }
        }
        else
        {
            int k;
            read(k);
            x=blo[k];y=blo[k];
            printf("%d\n",query(1,1<<h,1,k));
        }
    }
    
    return 0;
}

 

以上是关于NOI2017整数的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4942[Noi2017]整数 线段树+DFS(卡过)

noi2017 T1 整数 ——线段树

NOI2017整数

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

noi2017 整数 线段树or模拟

[BZOJ4942][NOI2017]整数(线段树+压位)