• 「题解」:玫瑰花精


    问题 C: 玫瑰花精

    时间限制: 1 Sec  内存限制: 256 MB

    题面


    题面谢绝公开。

    题解


    线段树记录四个信息:l、r、mid、p。

    l代表线段树该节点所管辖的区间内最左边的花精所在位置。r代表最右边花精所在位置。

    mid代表区间内相邻花精距离最大值除以二,p代表mid值所在的位置。

    考虑初始值:

    对于每一个线段树所管辖的每一个区间,$l=r=0$。$mid=p=0$。

    考虑转移过程:

    l取最左边,若左儿子的l有值,则为左儿子的l,否则若右儿子的l有值,l取右儿子的l,否则为0。r同理。

    mid先在左儿子的mid和右儿子的mid中取最大值,然后考虑跨区间的转移。

    若左儿子的r!=0,右儿子的l!=0,则mid=max(mid,(右儿子的l-左儿子的r)/2)。p相应更新。

    至于第一个花精进入判掉即可233。

    代码:

    #include<bits/stdc++.h>
    #define rint register int
    #define lc(A) (A<<1)
    #define rc(A) (A<<1|1)
    using namespace std;
    int n,m,vis[1000006];
    struct node{int l,r,mid,p;}t[1000006<<5];
    inline int get_dis()
    {
        if(t[1].l==0)return 1;
    //    cout<<t[1].l-1<<' '<<n-t[1].r<<' '<<t[1].mid<<endl;
        int lin=max(max(t[1].l-1,n-t[1].r),t[1].mid);
        if(lin==t[1].l-1)return 1;
        else if(lin==t[1].mid)return t[1].p;
        else return n;
    }
    inline void update(int k)
    {
        t[k].l=(t[lc(k)].l)?t[lc(k)].l:t[rc(k)].l;
        t[k].r=(t[rc(k)].r)?t[rc(k)].r:t[lc(k)].r;
        t[k].mid=max(t[lc(k)].mid,t[rc(k)].mid);
        int lin_l=t[lc(k)].r,lin_r=t[rc(k)].l;
        if(lin_l&&lin_r)t[k].mid=max(t[k].mid,(lin_r-lin_l)>>1);
        if(t[k].mid==t[lc(k)].mid)t[k].p=t[lc(k)].p;
        else if(t[k].mid==(lin_r-lin_l)>>1)t[k].p=(lin_l+lin_r)>>1;
        else t[k].p=t[rc(k)].p;
        return ;
    }
    inline void add(int k,int l,int r,int p)
    {
        if(l==r)
        {
            t[k].l=t[k].r=l;
            t[k].p=t[k].mid=0;
            return ;
        }
        int mid=(l+r)>>1;
        if(p<=mid)add(lc(k),l,mid,p);
        else add(rc(k),mid+1,r,p);
        update(k);
    }
    inline void del(int k,int l,int r,int p)
    {
        if(l==r)
        {
            t[k].l=t[k].r=0;
            t[k].p=t[k].mid=0;
            return ;
        }
        int mid=(l+r)>>1;
        if(p<=mid)del(lc(k),l,mid,p);
        else del(rc(k),mid+1,r,p);
        update(k);
    }
    int main()
    {
        scanf("%d %d",&n,&m);
        for(rint i=1,cz,x;i<=m;++i)
        {
            scanf("%d %d",&cz,&x);
            if(cz==1)
            {
                vis[x]=get_dis();
                add(1,1,n,vis[x]);
                printf("%d
    ",vis[x]);
            }
            else del(1,1,n,vis[x]);
        }
        return 0;
    }
    /*
    7 11
    1 15
    1 123123
    1 3
    1 5
    2 123123
    2 15
    1 21
    2 3
    1 6
    1 7
    1 8
    */
    View Code
  • 相关阅读:
    subprocess
    bytes(str_, encoding="utf8")
    按文件生成时间 排序 批量与生成同步上传文件
    async
    http trigger 事件源是事件的生产者,函数是事件的处理者
    分片上传
    使用 FFmpeg 处理高质量 GIF 图片
    兴趣 主题 字段 二值化 多值并列属性 拆分 二值化
    打开 回收站
    shell如何查看单个或多个文件的行数或总行数
  • 原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11495806.html
Copyright © 2020-2023  润新知