zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 数的统计
    Java实现 蓝桥杯VIP 算法训练 和为T
    Java实现 蓝桥杯VIP 算法训练 友好数
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 暗恋
    Java实现 蓝桥杯VIP 算法训练 暗恋
    测试鼠标是否在窗口内,以及测试鼠标是否在窗口停留
    RichEdit 各个版本介绍
  • 原文地址:https://www.cnblogs.com/Gloid/p/9400710.html
Copyright © 2011-2022 走看看