zoukankan      html  css  js  c++  java
  • NOIP2017 列队 线段树(指针版)+vector

    题目描述
    题目

    考试有想过每行建一棵树,但是发现空间会爆,就去打模拟了。。。
    然而,正解就是每行建一棵树(最后一列单独建一棵),只不过是把插入操作改成删除操作就好了。
    因为每次离队影响到的只会是人所在的行和列(如果是最后一列的离队只会影响行)。
    对于后面插进来的元素用vector存一下就好

    懒得去算要开多大的空间,并且最近玩数据结构玩得有点疯,就打了个指针版的线段树(并没有和打平衡树一样查错查半天,有点开心)

    下面是代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define ll long long
    using namespace std;
    const int N=300010;
    ll n,m,q,mn;
    
    struct node
    {
        node* ch[2];ll s;
        node(){ch[0]=ch[1]=NULL;s=1;}
        void maintain()
        { 
            s=0; 
            if(ch[0] != NULL) s+=ch[0]->s; 
            if(ch[1] != NULL) s+=ch[1]->s; 
        }
    };
    node* rt[N];
    vector<ll> g[N];
    
    ll query(node* o,ll l,ll r,ll x)
    {
        if(o == NULL) return l+x-1;
        if(l == r) return l;
        int mid=(l+r)>>1,ss=(o->ch[0]==NULL?0:o->ch[0]->s);   
        int h=mid-l+1-ss;   
        if(h >= x) return query(o->ch[0],l,mid,x);
        return query(o->ch[1],mid+1,r,x-h);
    }
    
    void del(node* &o,ll l,ll r,ll x)
    {
        if(o == NULL) o=new node();
        if(l == r) return ;
        int mid=(l+r)>>1;
        if(x <= mid) del(o->ch[0],l,mid,x);
        else del(o->ch[1],mid+1,r,x);
        o->maintain();
    }
    
    ll del_row(ll x)
    {
        ll idx=query(rt[n+1],1,mn,x);
        del(rt[n+1],1,mn,idx);
        if(idx > n) return g[n+1][idx-n-1];
        return idx*m;
    }
    
    ll del_line(ll x,ll y)
    {
        ll idx=query(rt[x],1,mn,y);
        del(rt[x],1,mn,idx);
        if(idx >= m) return g[x][idx-m];
        return (x-1)*m+idx;
    }
    
    int read()
    {
        int out=0,f=1;char c=getchar();
        while(c < '0' || c > '9') {if(c == '-') f=-1;c=getchar();}
        while(c >= '0' && c <= '9' ) 
        {out=(out<<1)+(out<<3)+c-'0';c=getchar();}
        return out*f;
    }
    
    void solve()
    {
        n=read();m=read();q=read();mn=max(n,m)+q;
        for(int i=1;i<=n+1;i++) rt[i]=NULL;
        for(int i=1;i<=q;i++)
        {
            ll x=read(),y=read();
            if(y == m)
            {
                ll id=del_row(x);
                g[n+1].push_back(id);
                printf("%lld
    ",id);
            }
            else
            {
                ll id1=del_line(x,y),id2=del_row(x);
                g[x].push_back(id2);g[n+1].push_back(id1);
                printf("%lld
    ",id1);
            }
        }
    }
    
    int main()
    {
        solve();
        return 0;
    }
    
  • 相关阅读:
    GIT SSH免登录密码实现更新(git pull)、推送(git push)操作
    Gulp新手入门教程
    常见的反爬虫的方式
    retrying模块的使用
    通过pyppeteer来爬取今日头条
    Selenium详解
    scrapy框架来爬取壁纸网站并将图片下载到本地文件中
    Elasticsearch简介
    使用scrapy框架来进行抓取的原因
    python(三):面向对象--类和实例
  • 原文地址:https://www.cnblogs.com/zerolt/p/9260903.html
Copyright © 2011-2022 走看看