NOIP2017 列队 线段树(指针版)+vector

来源:互联网 发布:微信看不到淘宝链接 编辑:程序博客网 时间:2024/06/09 22:47

题目描述
题目

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

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

下面是代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<vector>#define ll long longusing 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\n",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\n",id1);        }    }}int main(){    solve();    return 0;}
原创粉丝点击