splay

自顶向下splay

纯手写,没有借鉴他人写法,写得丑也木办法了。

伪代码借鉴http://wenku.baidu.com/view/b9cc2c75a417866fb84a8ee4.html

zkw神犇有漂亮的实现,但是不喜欢指针,所以只能自己yy

纯水:

near

给出N个数,问对于第i(i>=2)个数,从1到i-1中与它最接近的数与它的差是多少。

插入即查询,所以只需一次提根就都完成,速度比一般splay快一倍,比某些递归版treap快。

#include <cstdio>
#include <cstdlib>
#include <cstring>
int n,l[100000],r[100000],id[100000],mid,ll,rr,lr,rl,ss,ans;
const int oo=1073741819;
int min(int x,int y) {return (x<y) ? x : y;}
int right(int x,int y) {l[y]=r[x],r[x]=y;return x;}
int left(int x,int y)  {r[y]=l[x],l[x]=y;return x;}
void rconnect(int x){if (0==rr) {rl=rr=x;return ;}l[rl]=x,rl=x;}
void lconnect(int x){if (0==ll) {lr=ll=x;return ;}r[lr]=x,lr=x;}
int ask(int x)
{
  int sum=oo,y;
  ll=rr=lr=rl=0;
  for (;(id[mid]!=x)&&(mid);)
    if (id[mid]>x) {
      if ((id[l[mid]]>x)&&(l[mid])) mid=right(l[mid],mid);
      rconnect(mid),y=mid,mid=l[mid],l[y]=0;
    }
    else {
      if ((id[r[mid]]<x)&&(r[mid])) mid=left(r[mid],mid);
      lconnect(mid),y=mid,mid=r[mid],r[y]=0;
    }
  if (0==mid) mid=++ss,id[mid]=x;else sum=0;
  if (l[mid]) lconnect(l[mid]);
  if (r[mid]) rconnect(r[mid]);
  l[mid]=ll,r[mid]=rr;
  if (lr) sum=min(sum,x-id[lr]);
  if (rl) sum=min(sum,id[rl]-x);
  return sum;
}
void init()
{
  int i,x;
  scanf("%d\n",&n);scanf("%d",&x);
  id[mid=1]=x,ss=1;
  for (i=2;i<=n;i++)
  {
    scanf("%d",&x);
    ans=ask(x);
    printf("%d\n",ans);
  }
}
int main()
{
  freopen("near.in","r",stdin);
  freopen("near.out","w",stdout);
    init();
  return 0;
}

poj 3580

题意:http://blog.sina.com.cn/s/blog_6c7729450100uv8k.html

交换区间比较麻烦,参考了http://blog.csdn.net/pouy94/article/details/5751183

需要4次提根

#include <cstdio>
#include <cstdlib>
#include <cstring>
const int maxn=300000,oo=1073741819;
int n,m,ans,e,ll,rr,lr,rl,mid,ss;
int l[maxn],r[maxn],ls[maxn],rs[maxn],sum[maxn],id[maxn],size[maxn],t[maxn],a[maxn],op[maxn];
inline int min(int x,int y) {return (x<y) ? x : y;}
inline void swap(int x) {if (0==x) return ;e=l[x],l[x]=r[x],r[x]=e,id[x]=size[l[x]]+1;}
inline void pushdown(int x)
{ if (0==x) return ;
  if ((0==t[x])&&(0==op[x])) return ;
  if (t[x]) {
    if (l[x]) sum[l[x]]+=t[x],a[l[x]]+=t[x],t[l[x]]+=t[x];
    if (r[x]) sum[r[x]]+=t[x],a[r[x]]+=t[x],t[r[x]]+=t[x];
  }
  if (op[x]) swap(l[x]),swap(r[x]),op[l[x]]^=1,op[r[x]]^=1;
  t[x]=op[x]=0;
}
inline void updata(int x) 
  {if (0==x) return ;size[x]=size[l[x]]+size[r[x]]+1,sum[x]=min(a[x],min(sum[l[x]],sum[r[x]])),id[x]=size[l[x]]+1;}
inline int left(int x,int y) {pushdown(x),r[y]=l[x],l[x]=y,updata(y);return x;}
inline int right(int x,int y){pushdown(x),l[y]=r[x],r[x]=y,updata(y);return x;}
inline void lconnect(int x) {if (0==ll) {ll=lr=x,ls[ls[0]=1]=x;return ;}r[lr]=x,lr=x,ls[++ls[0]]=x;}
inline void rconnect(int x) {if (0==rr) {rr=rl=x,rs[rs[0]=1]=x;return ;}l[rl]=x,rl=x,rs[++rs[0]]=x;}
inline void splay(int &mid,int x)
{
  int i,y;
  ll=rr=lr=rl=rs[0]=ls[0]=0;
  for (;x!=(id[mid]-1);) {
      pushdown(mid);
      if (x>(id[mid]-1)) {  x-=id[mid];
          if ((x>(id[r[mid]]-1))&&(r[mid])) x-=id[r[mid]],mid=left(r[mid],mid);
          lconnect(mid),y=r[mid],r[mid]=0,mid=y;         
      }
      else {  
          if ((x<(id[l[mid]]-1))&&(l[mid])) mid=right(l[mid],mid);
          rconnect(mid),y=l[mid],l[mid]=0,mid=y;
      }
  }
  pushdown(mid),pushdown(l[mid]),pushdown(r[mid]);
  if (l[mid]) lconnect(l[mid]),ls[0]--;
  if (r[mid]) rconnect(r[mid]),rs[0]--;
  for (i=ls[0];i>=1;i--) updata(ls[i]);
  for (i=rs[0];i>=1;i--) updata(rs[i]);
  l[mid]=ll,r[mid]=rr,updata(mid);
}
inline int build(int ll,int rr)
{
  int mid=(ll+rr)>>1;
  if (mid+1<=rr) r[mid]=build(mid+1,rr);
  if (ll<=mid-1) l[mid]=build(ll,mid-1);
  updata(mid);return mid;
}
void init()
{
  int i,al,ar,ak,mo,aa,bb,cc,y;
  char ch[100];
  scanf("%d\n",&n);n+=2;
  for (i=2;i<=n-1;i++) scanf("%d\n",&a[i]),sum[i]=a[i],size[i]=1;
  size[1]=size[n]=1,sum[1]=sum[n]=oo,a[1]=a[n]=oo;  
  sum[0]=a[0]=oo,mid=build(1,n);
  scanf("%d\n",&m);
  for (i=1,ss=n;i<=m;i++)
  {
    scanf("%s",ch+1);
    if ('A'==ch[1]) {
        scanf("%d%d%d\n",&al,&ar,&ak);al++,ar++;
        splay(mid,ar);
        splay(l[mid],al-2);
        al=r[l[mid]];
        t[al]+=ak,sum[al]+=ak,a[al]+=ak;
        updata(l[mid]),updata(mid);
    }
    else if (('R'==ch[1])&&('E'==ch[4])) {
        scanf("%d%d\n",&al,&ar);al++,ar++;
        splay(mid,ar);
        splay(l[mid],al-2);
        al=r[l[mid]];
        swap(al),op[al]^=1;
    }
    else if (('R'==ch[1])&&('O'==ch[4])) {
        scanf("%d%d%d\n",&al,&ar,&ak);al++,ar++;
        mo=(ar-al+1),ak=(ak+mo)%mo;
        aa=al,bb=ar-ak,cc=ar;
        if ((bb<aa)||(bb+1>cc)) continue;
        splay(mid,bb-1);
        splay(l[mid],aa-2);
        splay(r[mid],cc-id[mid]);
        y=l[mid],l[mid]=r[y],r[y]=l[r[mid]],l[r[mid]]=0;
        updata(r[mid]),updata(mid),updata(y);
        splay(mid,0);       //splay(y,cc-);
        l[mid]=y;updata(mid);
    }
    else if ('I'==ch[1]) {
        scanf("%d%d\n",&al,&ak);al++;
        splay(mid,al);
        splay(l[mid],al-1);
        r[l[mid]]=++ss;
        sum[ss]=a[ss]=ak,size[ss]=1,id[ss]=1;
        updata(l[mid]),updata(mid);
    }
    else if ('D'==ch[1]) {
        scanf("%d%d\n",&al);al++;
        splay(mid,al);
        splay(l[mid],al-2);
        r[l[mid]]=0;
        updata(l[mid]),updata(mid);
    }
    else if ('M'==ch[1]) {
        scanf("%d%d\n",&al,&ar);al++,ar++;
        splay(mid,ar);
        splay(l[mid],al-2);
        ans=sum[r[l[mid]]];
        printf("%d\n",ans);
    }
  }
}
int main()
{
  freopen("3580.in","r",stdin);
  freopen("3580.out","w",stdout);
    init();
  return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值