51nod 1207

来源:互联网 发布:芒果tv破解版mac 编辑:程序博客网 时间:2024/06/05 21:37

#include <bits/stdc++.h>#define rep(ii,a,b) for (int ii=(a);ii<=(b);ii++)#define rek(ii,a,b) for (int ii=(a);ii>=(b);ii--)using namespace std;const int maxn=100010;int n,m;int len;int fa[maxn],c[maxn][2],siz[maxn],lx[maxn],rx[maxn],maxs[maxn],sta[maxn];int root;void updata(int x){    if (x==0) return;    siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;    maxs[x]=rx[x]-lx[x]+1;    if (c[x][0]) maxs[x]=max(maxs[x],maxs[c[x][0]]);    if (c[x][1]) maxs[x]=max(maxs[x],maxs[c[x][1]]);}void link(int x,int y,int der){    if (x!=0) c[x][der]=y;    if (y!=0) fa[y]=x;    updata(x);}void cut(int x,int y,int der){    updata(x);    if (x!=0) c[x][der]=0;    if (y!=0) fa[y]=0;    updata(x);}void rorate(int x){    if (fa[x]==0) return ;    int t=fa[x],t1=fa[fa[x]];    int p=(c[t][1]==x);    int p1=(c[fa[t]][1]==t);    link(t1,x,p1);    link(t,c[x][!p],p);    link(x,t,!p);    updata(t);}void splay(int x,int y){    while (fa[x]!=y){      if (fa[fa[x]]!=y){         if ((c[fa[x]][0]==x)^(c[fa[fa[x]]][0]==fa[x])){               rorate(x);          }else{             rorate(fa[x]);         }    }      rorate(x);    }    updata(x);    if (y==0) root=x; else updata(y);}int getrank(int x,int k){    int i=x;    int j=k;    while (true){        if (j==siz[c[i][0]]+1) return i;        if (siz[c[i][0]]+1<j) {            j-=(siz[c[i][0]]+1);            i=c[i][1];        } else{            i=c[i][0];        }    }}void del(int now){     splay(now,0);     int i=c[now][0];     while (c[i][1]) i=c[i][1];     int j=c[now][1];     while (c[j][0]) j=c[j][0];     splay(i,0);     splay(j,i);     c[j][0]=0;     updata(j);     updata(i);}int getnext(int now){    splay(now,0);    int i=c[now][1];    while (c[i][0]) i=c[i][0];    return i;}int getlast(int now){    splay(now,0);    int i=c[now][0];    while (c[i][1]) i=c[i][1];    return i;}int solve(int x){    int i=root;    if (maxs[i]<x) return -1;    while (i){        if (maxs[c[i][0]]>=x && c[i][0]!=0) i=c[i][0];else {                if (rx[i]-lx[i]+1>=x && rx[i]<=n && lx[i]>=0)                        {                            int ans=lx[i];                            splay(i,0);                            lx[i]+=x;                            updata(i);                            if (lx[i]>rx[i]) del(i);                            return ans;                        }                i=c[i][1];        }    }}bool pd_lr(int l,int r,int ll,int rr){    if (l>ll) {swap(l,ll);swap(r,rr);}    if (r==ll-1) return true;    if (r<ll) return false;    if (l>rr) return false;    return true;}void cover(int l,int r){    int i=root,j,ans=0;    while (i){        if (rx[i]>=l)        if ((ans==0)||(rx[ans]>rx[i])) ans=i;        if (rx[i]>=l) i=c[i][0];else i=c[i][1];    }    int tlast=getlast(ans);    if (lx[ans]>r+1 && rx[tlast]!=l-1) {        len++;        splay(ans,0);        int j=c[root][0];        while (c[j][1]) j=c[j][1];        splay(j,root);        lx[len]=l;rx[len]=r;        updata(len);        link(j,len,1);        updata(root);        return ;    }    int tt=0,ll=l,rr=r;    i=ans;    if (pd_lr(ll,rr,lx[tlast],rx[tlast])) {i=tlast;tlast=getlast(tlast);}    while (pd_lr(ll,rr,lx[i],rx[i])){        if (lx[i]<ll) ll=lx[i];        if (rx[i]>rr) rr=rx[i];        tt++;        sta[tt]=i;        i=getnext(i);    }    rep(i,1,tt) del(sta[i]);    splay(tlast,0);    i=c[tlast][1];    while (c[i][0]) i=c[i][0];    splay(i,root);    len++;    lx[len]=ll;rx[len]=rr;    maxs[len]=rr-ll+1;    siz[len]=1;    link(i,len,0);    updata(root);}int main(){    freopen("input.txt","r",stdin);    freopen("output.txt","w",stdout);    scanf("%d%d",&n,&m);    len=3;    root=1;    lx[1]=0;rx[1]=n-1;    lx[2]=-1;rx[2]=-2;    lx[3]=n+4;rx[3]=n+3;    c[root][0]=2;    c[root][1]=3;    fa[2]=1;fa[3]=1;    rek(i,3,1) updata(i);    rep(i,1,m)     {        int c,x,y;        scanf("%d",&c);        if (c==1) {                scanf("%d",&x);                printf("%d\n",solve(x));        }else        {            scanf("%d%d",&x,&y);            int l=x;            int r=min(x+y-1,n);            cover(l,r);        }    }    return 0;}

题意不说了。

很显然,这题我们可以用splay做,每个节点维护一段连续的未被占用的区间,以及所在该子树最长的区间。。。这个非常好维护。。比较蛋疼的是2操作,要把所有相关的区间提取出来求并。。然后再插入新节点。。。就是模拟而已。当然也可以用动态开节点的线段树。。不过本人抖m写了个splay

代码:


0 0
原创粉丝点击