• [2016北京集训测试赛5]小Q与内存-[线段树的神秘操作]


    Description

    Solution

    哇真的异常服气。。线段树都可以搞合并和拆分的啊orzorz。神的世界我不懂

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int M=20000010;
    const int N=200010;
    int sz[M],lc[M],rc[M],tag[M],rt[N],all_work,cnt;
    int _new(int x=1)
    {
        int o=++cnt;
        tag[o]=x-1;
        sz[o]=1<<tag[o];
        lc[o]=rc[o]=0;
        return cnt;
    }
    void pushdown(int o)
    {
        if (!tag[o]) return;
        lc[o]=_new(tag[o]);
        rc[o]=_new(tag[o]);
        tag[o]=0;
    }
    int split(int o,int k)
    {
        int now=++cnt,re=now;
        pushdown(o);
        while (lc[o]||rc[o])
        {
            tag[now]=0;sz[now]=k;sz[o]-=k;
            if (k<=sz[lc[o]])
            {
                lc[now]=_new();rc[now]=0;
                now=lc[now];o=lc[o];
            } else
            {
                rc[now]=_new();lc[now]=lc[o];
                k-=sz[lc[o]];lc[o]=0;
                now=rc[now];o=rc[o];
            }
            pushdown(o);
        }
        tag[now]=tag[o]=0;
        sz[now]=k;sz[o]-=k;
        return re;
    }
    int merge(int x,int y)
    {
        if (!x||!y) return x+y;
        lc[x]=merge(lc[x],lc[y]);
        rc[x]=merge(rc[x],rc[y]);
        sz[x]+=sz[y];
        return x;
    }
    int query(int x,int k)
    {
        int o=rt[x];
        if (x>all_work||k>=sz[o]) return -1;
        int re=0;
        while (lc[o]||rc[o])
        {
            re<<=1;
            if (lc[o]&&k<sz[lc[o]]) o=lc[o];
            else k-=sz[lc[o]],re|=1,o=rc[o];
        }
        return re*(1<<tag[o])+k;
    }
    int T,n,root;
    int _type,_k,_i,_p;
    void clear()
    {
        cnt=all_work=0;
        root=_new(31);
    }
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            clear();
            scanf("%d",&n);
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&_type);
                if (_type==1)
                {
                    scanf("%d",&_k);
                    all_work++;
                    rt[all_work]=0;
                    if (sz[root]<_k) {printf("failed
    ");continue;}
                    rt[all_work]=split(root,_k);
                    printf("ok
    ");
                }
                if (_type==2)
                {
                    scanf("%d",&_i);
                    if (_i>all_work||!rt[_i]) {printf("failed
    ");continue;}
                    root=merge(root,rt[_i]);rt[_i]=0;
                    printf("ok
    ");
                }
                if (_type==3)
                {
                    scanf("%d%d",&_i,&_p);
                    int ans=query(_i,_p);
                    if (ans!=-1) printf("%d
    ",ans);
                    else printf("failed
    ");
                }
            }
        }
    }
  • 相关阅读:
    刷题总结——疫情控制(NOIP2012提高组)
    刷题总结——竞赛得分(ssoj)
    刷题总结——货车运输
    刷题总结——火柴排队(NOIP2013)
    刷题总结——烽火传递(单调队列+dp)
    刷题总结——道路覆盖(ssoj)
    刷题总结——过河(NOIP2015)
    刷题总结——子串(NOIP2015提高组)
    linux shell 学习笔记--文件测试符
    linux shell 学习笔记--比较操作
  • 原文地址:https://www.cnblogs.com/coco-night/p/9640928.html
Copyright © 2020-2023  润新知