首页 > 其他分享 >P2596 [ZJOI2006]书架

P2596 [ZJOI2006]书架

时间:2023-05-02 14:44:39浏览次数:52  
标签:书架 int text P2596 ls 编号 ZJOI2006

\(\color{purple}\text{P2596 [ZJOI2006]书架}\)

解题方法

考虑使用 \(\text{FHQ}\) 平衡树 ,我们只使用编号,而不使用权值,平衡树上的先序遍历即为书的放置顺序。

  1. \(\text{Query}\) :这是最简单的操作,直接查询即可。
  2. \(\text{Ask}\):本题的核心,我们知道编号,因为没有权值,没法从根往下找到询问点,如果强制设权值会很麻烦。正难则反,既然我们知道询问点的编号,不如从询问点向上走回根,这个操作需要我们维护每个节点的父亲。(记得每次树改变时把根的父亲设为 \(0\) )
  3. \(\text{Bottom/Top/Insert}\) 既然已经有了 \(Ask\) ,我们可以直接通过编号找到排名,继而分裂出需要改变的点,剩下的就是重新组合。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int n,m,rl[N],fx[N];
struct FHQ{
	int rt,x,y,z,cnt,phi;
	int ls[N],rs[N],rad[N],sze[N];
	int fa[N];
	void pushup(int u){sze[u]=sze[ls[u]]+sze[rs[u]]+1;return;} 
	int newnode(){
		rad[++cnt]=rand();
		sze[cnt]=1;
		return cnt;
	}
	void split(int u,int k,int &x,int &y,int fax,int fay){
		if(!u)x=0,y=0;
		else{
			if(k>sze[ls[u]]){
				x=u;fa[u]=fax;
				split(rs[u],k-sze[ls[u]]-1,rs[u],y,u,fay);
			}
			else{
				y=u;fa[u]=fay;
				split(ls[u],k,x,ls[u],fax,u);
			}
			pushup(u);
		}
		return;
	}
	int merge(int A,int B){
		if(!A || !B)return A+B;
		if(rad[A]<rad[B]){rs[A]=merge(rs[A],B);fa[rs[A]]=A;pushup(A);return A;}
		else {ls[B]=merge(A,ls[B]);fa[ls[B]]=B;pushup(B);return B;}
	}
	void insert(){rt=merge(rt,newnode());return;}
	int Query(int k){
		split(rt,k,x,z,0,0);
		split(x,k-1,x,y,fa[x],fa[y]);
		int tmp=y;rt=merge(merge(x,y),z);fa[rt]=0;
		return tmp;
	} 
	int ask(int x,int fr){
		if(x==0)return 0;
		if(fr==ls[x])return ask(fa[x],x);
		else return ask(fa[x],x)+sze[ls[x]]+1; 
	}
	int Ask(int x){return ask(fa[x],x)+sze[ls[x]];}
	void top(int k){
		split(rt,k-1,x,y,fa[x],fa[y]);
		split(y,1,y,z,fa[y],fa[z]);
		rt=merge(y,merge(x,z));fa[rt]=0;
	}
	void bottom(int k){
		split(rt,k-1,x,y,fa[x],fa[y]);
		split(y,1,y,z,fa[y],fa[z]);
		rt=merge(merge(x,z),y);fa[rt]=0;
	}
	void sap(int k,int t){
		if(t==-1){
			split(rt,k-2,x,y,fa[x],fa[y]);
			split(y,1,y,z,fa[y],fa[z]);
			split(z,1,z,phi,fa[z],fa[phi]);
			rt=merge(merge(x,z),merge(y,phi));fa[rt]=0;
		}
		if(t==1){
			split(rt,k-1,x,y,fa[x],fa[y]);
			split(y,1,y,z,fa[y],fa[z]);
			split(z,1,z,phi,fa[z],fa[phi]);
			rt=merge(merge(x,z),merge(y,phi));fa[rt]=0;
		}
		return;
	}
	void sd(int u){
		if(!u)return;
		cout<<u<<" "<<sze[u]<<" "<<ls[u]<<" "<<rs[u]<<" "<<fa[u]<<endl;
		sd(ls[u]);
		sd(rs[u]);
	}
	void Bark(){
		printf("-----------HYC is here-----------\n");
		sd(rt);
		printf("-----------HYC has gone-----------\n");
	}
}T;
int main(){
	srand(20230502);
	n=read(),m=read();
	for(int i=1;i<=n;i++)rl[i]=read(),fx[rl[i]]=i;//树编号-》实际编号;实际编号-》树编号 
	for(int i=1;i<=n;i++)T.insert();
//	T.Bark(); 
	for(int i=1;i<=m;i++){
		char opt[10];scanf("%s",opt);
		if(opt[0]=='Q'){int k=read();printf("%d\n",rl[T.Query(k)]);}
		if(opt[0]=='A'){int x=read();printf("%d\n",T.Ask(fx[x]));}
		if(opt[0]=='T'){int x=read();T.top(T.Ask(fx[x])+1);}
		if(opt[0]=='B'){int x=read();T.bottom(T.Ask(fx[x])+1);}
		if(opt[0]=='I'){int x=read(),t=read();T.sap(T.Ask(fx[x])+1,t);}
//		T.Bark(); 
	}
	return 0;
}

标签:书架,int,text,P2596,ls,编号,ZJOI2006
From: https://www.cnblogs.com/FJOI/p/17367678.html

相关文章

  • 超级书架2 计蒜客 - T1736(01背包应用,好题)
    题意:FarmerJohn最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留有一点空间。所有N(1≤N≤......
  • P1772 [ZJOI2006] 物流运输
    P1772[ZJOI2006]物流运输题意:需要将物品从\(A\)移动到\(B\),需要\(n\)天才能运输完成,运输过程中需要转停很多个码头。求指定一个\(n\)天的运输计划,使得总成本......
  • 基于halo搭建的满心书架
    基于html写的静态书架,没有后台,所有书籍的图片和链接都有自己手动添加,感兴趣的小伙伴可以去试试体验地址预览效果:使用​​halo​​​创建页面,单独嵌入​​html​​,预览效果如......
  • Luogu P1772 [ZJOI2006]物流运输
    题目链接:​​传送门​​很麻烦也很难想的一道题数据很小大胆yy详细解释在代码里#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<co......
  • 做题记录整理dp15 P1772. [ZJOI2006] 物流运输(2022/9/28)
    P3648[APIO2014]序列分割第一次做斜率优化的题题解看懂了,但没有完全看懂等以后得回来看一次#include<bits/stdc++.h>#definefor1(i,a,b)for(inti=a;i<=b;i++)......
  • P1772 [ZJOI2006] 物流运输
    #include<bits/stdc++.h>usingnamespacestd;constintMAXN=1e8;classsolve{ public: intn,m,k,E; priority_queue<pair<int,int>>q; structnode{......
  • 做题记录整理dp15 P1772. [ZJOI2006] 物流运输(2022/9/28)
    P1772.[ZJOI2006]物流运输图论+dp首先看数据范围这么小,其实就可以猜到很可能是先把i到j天的最短路都求出来然后就会发现dp方程很简单了dp[i]=min(dp[j]+最短路[j+1][......
  • luogu P1772 [ZJOI2006] 物流运输 (dp, 最短路)
    https://www.luogu.com.cn/problem/P1772虽然是图论背景,但是1-n天之间是线性关系。没法贪心决策,考虑dp:我本来写的dp是i-1转移到i,但是这样没法处理哪一天能走哪些最短路......