关闭

51nod 1207

标签: 数据结构splay51nod
177人阅读 评论(0) 收藏 举报

#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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3506次
    • 积分:130
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:2篇
    • 译文:0篇
    • 评论:0条
    文章分类