• BZOJ4942 NOI2017整数(线段树)


      首先把每32位压成一个unsigned int(当然只要压起来能过就行)。如果不考虑进/退位的话,每次只要将加/减上去的数拆成两部分直接单点修改就好了。那么考虑如何维护进/退位。可以发现进位的过程其实就是将一段连续的inf改为0,并把之后一位+1,也就是说只要找到某一位之后第一个不是inf的位就好了。我们用线段树维护这个东西,记录一下某个节点表示的区间是否全为inf。查询时先从叶子节点往上爬,直到当前节点代表的区间中在该叶子节点右边的位不全为inf时停止,之后再往下找最左的非inf位。退位类似。这样的话复杂度就是O(nlogn)。

      写起来挺烦的,注意一下各种细节,码力极弱选手表示调了快一天……惨惨。

    // luogu-judger-enable-o2
    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 1000010
    #define ui unsigned int
    #define inf 4294967295
    #define lson (k<<1)
    #define rson (k<<1|1)
    #define getmid; int mid=tree[k].l+tree[k].r>>1;
    int n;
    struct data{int l,r,tag,size,sumzero,suminf;ui num;
    }tree[N<<2];
    bool isleaf(int k){return tree[k].size==1;}
    void build(int k,int l,int r)
    {
        tree[k].l=l,tree[k].r=r,tree[k].size=r-l+1;
        tree[k].sumzero=tree[k].size,tree[k].suminf=0;
        if (isleaf(k)) return;
        getmid;
        build(lson,l,mid);
        build(rson,mid+1,r);
    }
    void up(int k)
    {
        tree[k].sumzero=tree[lson].sumzero+tree[rson].sumzero;
        tree[k].suminf=tree[lson].suminf+tree[rson].suminf;
    }
    void update(int k,int tag)
    {
        if (tag>0) tree[k].sumzero=tree[k].size,tree[k].suminf=0;
        else tree[k].sumzero=0,tree[k].suminf=tree[k].size;
        tree[k].tag=tag;
        if (isleaf(k)) tree[k].num=tag>0?0:inf;
    }
    void down(int k)
    {
        if (tree[k].tag)
        {
            update(lson,tree[k].tag);
            update(rson,tree[k].tag);
            tree[k].tag=0;
        }
    }
    int find(int k,int x)
    {
        if (isleaf(k)) return k;
        down(k);
        getmid;
        int ans;
        if (x<=mid) ans=find(lson,x);
        else ans=find(rson,x);
        up(k);
        return ans;
    }
    void modify(int k,int l,int r,int tag)
    {
        if (tree[k].l==l&&tree[k].r==r)
        {
            update(k,tag);
            return;
        }
        down(k);
        getmid;
        if (r<=mid) modify(lson,l,r,tag);
        else if (l>mid) modify(rson,l,r,tag);
        else modify(lson,l,mid,tag),modify(rson,mid+1,r,tag);
        up(k);
    }
    int add(int k,int p,ui x)
    {
        if (isleaf(k))
        {
            int v=inf-tree[k].num<x;
            tree[k].num+=x;
            tree[k].sumzero=(tree[k].num==0);
            tree[k].suminf=(tree[k].num==inf);
            return v;
        } 
        down(k);
        getmid;
        int ans;
        if (p<=mid) ans=add(lson,p,x);
        else ans=add(rson,p,x);
        up(k);
        return ans;
    }
    int dec(int k,int p,ui x)
    {
        if (isleaf(k))
        {
            int v=tree[k].num<x;
            tree[k].num-=x;
            tree[k].sumzero=(tree[k].num==0);
            tree[k].suminf=(tree[k].num==inf);
            return v;
        }
        down(k);
        getmid;
        int ans;
        if (p<=mid) ans=dec(lson,p,x);
        else ans=dec(rson,p,x);
        up(k);
        return ans;
    }
    void pushup(int k)
    {
        if (tree[k].suminf)
        {
            int t=k,cnt=0;
            while (tree[k].suminf-cnt==tree[k].r-tree[t].l+1) 
            {
                if (k&1) cnt+=tree[k-1].suminf;
                k>>=1;
            }
            k=rson;
            while (!isleaf(k))
            {
                down(k);
                if (tree[lson].suminf==tree[lson].size) k=rson;
                else k=lson;
            }
            modify(1,tree[t].l,tree[k].l-1,1);
        }
        add(1,tree[k].l,1);
    }
    void pushdown(int k)
    {
        if (tree[k].sumzero)
        {
            int t=k,cnt=0;
            while (tree[k].sumzero-cnt==tree[k].r-tree[t].l+1) 
            {
                if (k&1) cnt+=tree[k-1].sumzero;
                k>>=1;
            }
            k=rson;
            while (!isleaf(k))
            {
                down(k);
                if (tree[lson].sumzero==tree[lson].size) k=rson;
                else k=lson;
            }
            modify(1,tree[t].l,tree[k].l-1,-1);
        }
        dec(1,tree[k].l,1);
    }
    int query(int k,int p,int x)
    {
        if (isleaf(k)) return tree[k].num>>x&1;
        down(k);
        getmid;
        int ans;
        if (p<=mid) ans=query(lson,p,x);
        else ans=query(rson,p,x);
        up(k);
        return ans;
    }
    int main()
    {
        n=read();read(),read(),read();
        build(1,1,n+2);
        for (int i=1;i<=n;i++)
        {
            int op=read();
            if (op==1)
            {
                int x=read(),y=read();
                if (x>0)
                {
                    ui v=x;
                    ui a=v<<(y&31),b=(y&31)?(v>>(32-(y&31))):0;
                    if (a>0) b+=add(1,(y>>5)+1,a);
                    if (b>0)
                    {
                        a=add(1,(y>>5)+2,b);
                        if (a>0) pushup(find(1,(y>>5)+3));
                    }
                }
                else
                {
                    ui v=abs(x);
                    ui a=v<<(y&31),b=(y&31)?(v>>(32-(y&31))):0;
                    if (a>0) b+=dec(1,(y>>5)+1,a);
                    if (b>0)
                    {
                        a=dec(1,(y>>5)+2,b);
                        if (a>0) pushdown(find(1,(y>>5)+3));
                    }
                }
            }
            else
            {
                int x=read();
                printf("%d
    ",query(1,(x>>5)+1,x&31));
            }
        }
        return 0;
    }
  • 相关阅读:
    List集合中的对象按照某个字段去重实现
    菜单--微信提醒
    fastTime从后台传过来显示格式的处理
    彻底卸载Oracle
    关于这次安装Oracle
    关于下拉选择删选最基本一例(分享内容)
    马拉松参赛人员显示(瞬逝版)
    马拉松参赛人员旧版本最终版(私藏版)
    win 10 初始环境变量
    AngularJS输出helloworld
  • 原文地址:https://www.cnblogs.com/Gloid/p/9400710.html
Copyright © 2020-2023  润新知