HDU 2475 Box [dfs序+splay]
2015-10-23 13:45
369 查看
这题TLE了140+发,最终发现是自己对splay tree 的复杂度理解不够:每一次对树中节点的查询、修改、删除等操作,都需要进行一次splay,否则复杂度不能保证是均摊NlogN的。
回到这道题,题意是,给出N个箱子,每个箱子可以包含其他箱子,现在有操作MOVE (A,B),将A箱子移动到B箱子里,其中B作为直接父亲箱子(A会带着其包含的箱子一起MOVE),询问某一个箱子的最外层是哪个箱子。
范围:N<=5W,M<=10W;
解法:很明显是一个树上结构的问题,发现并查集不能很好解决(路径压缩会破坏结构),需要一个更好的方法。发现操作只与一棵子树有关,进而想到DFS序,发现移动箱子只是将一片区间剪到另一个位置,很明显用splay可以解决。
代码:(自带常数放大自动机,用者谨慎 orz)
回到这道题,题意是,给出N个箱子,每个箱子可以包含其他箱子,现在有操作MOVE (A,B),将A箱子移动到B箱子里,其中B作为直接父亲箱子(A会带着其包含的箱子一起MOVE),询问某一个箱子的最外层是哪个箱子。
范围:N<=5W,M<=10W;
解法:很明显是一个树上结构的问题,发现并查集不能很好解决(路径压缩会破坏结构),需要一个更好的方法。发现操作只与一棵子树有关,进而想到DFS序,发现移动箱子只是将一片区间剪到另一个位置,很明显用splay可以解决。
代码:(自带常数放大自动机,用者谨慎 orz)
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #include<iostream> #include<stdlib.h> #include<set> #include<map> #include<queue> #include<vector> #include<bitset> #pragma comment(linker, "/STACK:1024000000,1024000000") template <class T> bool scanff(T &ret){ //Faster Input char c; int sgn; T bit=0.1; if(c=getchar(),c==EOF) return 0; while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); if(c==' '||c=='\n'){ ret*=sgn; return 1; } while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10; ret*=sgn; return 1; } #define inf 1073741823 #define llinf 4611686018427387903LL #define PI acos(-1.0) #define lth (th<<1) #define rth (th<<1|1) #define rep(i,a,b) for(int i=int(a);i<=int(b);i++) #define drep(i,a,b) for(int i=int(a);i>=int(b);i--) #define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next) #define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++) #define mem(x,val) memset(x,val,sizeof(x)) #define mkp(a,b) make_pair(a,b) #define findx(x) lower_bound(b+1,b+1+bn,x)-b #define pb(x) push_back(x) using namespace std; typedef long long ll; typedef pair<int,int> pii; #define NN 402020 int n,m,rt,lnum,tot; int fa[NN],val[NN],a[NN],c[NN][2],sz[NN],bj[NN]; int ptx[NN],lo[NN],ro[NN],f[NN]; bool vis[NN]; struct edge{ int v,next; edge(){} edge(int vv,int nn):v(vv),next(nn){} }ed[NN]; void addline(int x,int y){ ed[lnum]=edge(y,ptx[x]); ptx[x]=lnum++; } void addnode(int x,int father){ tot++; a[tot]=x; if(father>0)f[tot]=f[lo[father]]; else f[tot]=x; } int pd; void dfs(int x,int father){ vis[x]=1; addnode(x,father);lo[x]=tot; gson(i,x){ int y=ed[i].v; if(vis[y]||y==father)continue; dfs(y,x); } addnode(x,father);ro[x]=tot; } inline void push(int x){ if(bj[x]){ f[x]=bj[c[x][0]]=bj[c[x][1]]=bj[x]; bj[x]=0; } } inline void update(int x){ sz[x]=1; if(c[x][0])sz[x]+=sz[c[x][0]]; if(c[x][1])sz[x]+=sz[c[x][1]]; } void rotate(int x,int &k){ int y=fa[x],z=fa[y],l,r; push(y);push(x); l=(c[y][1]==x);r=l^1; if(y==k)k=x; else c[z][c[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; update(y); } int sta[NN],top; void splay(int x,int &k){ for(push(x);x!=k;){ int y=fa[x],z=fa[y]; if(y!=k){ if(c[y][0]==x^c[z][0]==y)rotate(x,k); else rotate(y,k); } rotate(x,k); } update(x); } void built(int l,int r,int f){ if(l>r)return; int m=(l+r)>>1; c[f][m>=f]=m; fa[m]=f; sz[m]=1; val[m]=a[m]; bj[m]=0; if(l==r)return; built(l,m-1,m); built(m+1,r,m); update(m); } int getfront(int x){ splay(x,rt); x=c[x][0]; while(c[x][1]){ push(x); x=c[x][1]; } return x; } int getnext(int x){ splay(x,rt); x=c[x][1]; while(c[x][0]){ push(x); x=c[x][0]; } return x; } bool check(int x,int y){ while(x){ if(x==y)return true; x=fa[x]; } return false; } void move(int a,int b){ if(a<=0||a>n)return; int x,y,z; if(a==b)return; x=getfront(lo[a]); y=getnext(ro[a]); splay(x,rt); splay(y,c[x][1]); z=c[y][0]; if(check(lo[b],z))return; c[y][0]=0; update(y); x=lo[b]; y=getnext(x); splay(x,rt); splay(y,c[x][1]); c[y][0]=z; fa[z]=y; update(y); if(b==0)bj[z]=a; else bj[z]=f[x]; } void init(){ tot=0;lnum=0; rep(i,0,n)ptx[i]=-1,vis[i]=0; int x; rep(i,1,n){ scanff(x); addline(x,i); addline(i,x); } dfs(0,-1); rep(i,1,tot)c[i][0]=c[i][1]=0,bj[i]=0; built(1,tot,0); rt=(tot+1)>>1; } char op[111]; int main(){ int cas=0; while(scanf("%d",&n)!=EOF){ if(cas++)printf("\n"); init(); scanff(m); int x,y; rep(i,1,m){ scanf("%s",op); if(op[0]=='M'){ scanff(x);scanff(y); move(x,y); } else{ scanff(x); splay(lo[x],rt); printf("%d\n",f[lo[x]]); } } } return 0; }
相关文章推荐
- jxl.write.biff.RowsExceededException: The maximum number of rows permitted on a worksheet been excee
- Linux搭建vsftp
- Boost源码学习二[内存管理一]下
- 【程序员眼中的统计学(8)】统计抽样的运用:抽取样本
- idea快捷键
- Centos7安装MySQL常见问题
- BosonNLP分词技术解密
- top指令的部分参数讲解
- Android各种轮子
- poj3279-Fliptile 技巧1 开灯问题
- 【转】SQLServerDBA十大必备工具---让生活轻松点
- uitableview 优化
- Maven环境搭建、调试、打包
- LSGO软件技术团队与信息1402班开展真人CS活动
- android开发游记:viewpager关联tabs,自定义tabs实现翻页滚动效果
- Bat命令学习
- [C++] [算法] KMP算法
- 当用curl爬取数据时,如果想截取的内容前后html都含有换行符,空格,该如何处理
- 你容易忽视的mysql外键锁和自增锁
- ThinkPHP登录