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
- 51nod 1207
- 51Nod
- 51Nod
- 51nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- MFC中增加输出到控制台
- Eclipse 修改默认的author 作者
- Stop Spark Streaming On YARN Gracefully
- linux下mysql5.1乱码问题
- OC试题 ——通讯录(AddressBook)
- 51nod 1207
- centos7 在 selinux先 改ssh端口
- C++学习-多继承和虚基类
- DroidDraw界面设计软件
- ViewTreeObserver简介
- android接入原生第三方登录(微信登录、QQ登录、新浪微博登录)
- android蓝牙开发---与蓝牙模块进行通信
- Android Studio 使用3-ide界面简单预览
- MySQL5.6安装无法启动