zoukankan      html  css  js  c++  java
  • AHOI/HNOI2017单旋



    (m1e5)

    套路:题目是splay,就显然不是spaly

    单旋与双旋的区别:

    若为一条链,单旋完了还是链,复杂度不对

    双旋我们判断了如果与父亲及祖先在一条直线上则先转祖先,则不会发生这种情况

    SOL:

    发现其实树的形态变化并不大

    例如将最小值旋至根:

    1. 把最小值的儿子当做其父亲的对应儿子
    2. 让最小值做根节点

    深度变化:除最小值子树+1,即所有>=最小值父亲的值

    删除根节点则所有点-1

    考虑插入:

    插入值的前驱后继一定是连在一起的

    插入值只可能做前驱或后继的儿子,于是直接选深度最大的即可

    离散化+树状数组+set即可解决

    时间复杂度(O(nlog_n))

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    const int N=1e5+4;
    int m,cn,op[N],uu[N],b[N],rt,ch[N][2],fa[N],t[N];
    set<int>s;
    inline void add(int x,int v){
    	for(;x<=cn;x+=x&-x)t[x]+=v;
    }
    inline int ask(int x){
    	int ret=0;
    	for(;x;x-=x&-x)ret+=t[x];
    	return ret;
    }
    int main(){
    	m=read();
    	for(int i=1;i<=m;i++){
    		op[i]=read();
    		if(op[i]==1)uu[i]=b[++cn]=read();
    	}
    	sort(b+1,b+cn+1);
    	cn=unique(b+1,b+cn+1)-b-1;
    	for(int i=1,u,x,v;i<=m;i++){
    		if(op[i]==1){
    			u=lower_bound(b+1,b+cn+1,uu[i])-b;
    			set<int>::iterator it=s.lower_bound(u);
    			if(it!=s.end()&&!ch[*it][0]){
    				ch[*it][0]=u;
    				fa[u]=*it;
    				add(u,x=ask(*it)+1-ask(u));
    				add(u+1,-x);
    			}
    			else if(it!=s.begin()&&!ch[*(--it)][1]){
    				ch[*it][1]=u;
    				fa[u]=*it;
    				add(u,x=ask(*it)+1-ask(u));
    				add(u+1,-x);
    			}
    			else{
    				rt=u;
    				add(u,x=1-ask(u));
    				add(u+1,-x);
    			}
    			s.insert(u);
    			cout<<ask(u)<<"
    ";
    		}
    		else if(op[i]==2){
    			u=*s.begin();
    			cout<<ask(u)<<"
    ";
    			v=fa[u];
    			if(v){
    				add(v,1);
    				fa[ch[u][1]]=v;
    				ch[v][0]=ch[u][1];
    				add(u,x=1-ask(u));
    				add(u+1,-x);
    				ch[u][1]=rt;
    				fa[rt]=u;
    				fa[u]=0;
    				rt=u;
    			}
    		}
    		else if(op[i]==3){
    			u=*s.rbegin();
    			cout<<ask(u)<<"
    ";
    			v=fa[u];
    			if(v){
    				add(1,1);add(v+1,-1);
    				fa[ch[u][0]]=v;
    				ch[v][1]=ch[u][0];
    				add(u,x=1-ask(u));
    				add(u+1,-x);
    				ch[u][0]=rt;
    				fa[rt]=u;
    				fa[u]=0;
    				rt=u;
    			}
    		}
    		else if(op[i]==4){
    			u=*s.begin();
    			cout<<ask(u)<<"
    ";
    			v=fa[u];
    			if(v){
    				add(v,1);
    				fa[ch[u][1]]=v;
    				ch[v][0]=ch[u][1];
    				add(u,x=1-ask(u));
    				add(u+1,-x);
    				ch[u][1]=rt;
    				fa[rt]=u;
    				fa[u]=0;
    				rt=u;
    			}
    			fa[rt=ch[u][1]]=0;
    			add(1,-1);
    			s.erase(u);
    		}
    		else{
    			u=*s.rbegin();
    			cout<<ask(u)<<"
    ";
    			v=fa[u];
    			if(v){
    				add(1,1);add(v+1,-1);
    				fa[ch[u][0]]=v;
    				ch[v][1]=ch[u][0];
    				add(u,x=1-ask(u));
    				add(u+1,-x);
    				ch[u][0]=rt;
    				fa[rt]=u;
    				fa[u]=0;
    				rt=u;
    			}
    			fa[rt=ch[u][0]]=0;
    			add(1,-1);
    			s.erase(u);
    		}
    	}
    	return (0-0);
    }
    
  • 相关阅读:
    启动hadoop 2.6遇到的datanode启动不了
    .net开发遇到的一个问题
    there are 0 datanode.....
    更改HDFS权限
    VMware提示:已将该虚拟机配置为使用 64 位客户机操作系统。但是,无法执行 64 位操作。解决方案
    Hive学习
    linux下mysql安装
    (5.2)mysql高可用系列——测试环境部署
    【转】mysql索引的探究
    【3.1】【mysql基本实验】mysql复制(主从复制/异步复制/半同步复制,一主一从)
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12519495.html
Copyright © 2011-2022 走看看