把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【BZOJ1803】Query on a tree III(主席树SB题)

点此看题面

大致题意: 求子树第\(k\)大。

\(SB\)

显然求出原序列的\(dfs\)序列,然后子树就变成了一个区间。

动态第\(k\)大可以用树套树(分块:?),静态第\(k\)大直接主席树就好了,显然是裸题。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LN 25
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n,a[N+5],g[N+5],ee,lnk[N+5],d,dI[N+5],dO[N+5],f[N+5];struct edge {int to,nxt;}e[N<<1];
class FastIO
{
	private:
		#define FS 100000
		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
		#define pc(c) (C==E&&(clear(),0),*C++=c)
		#define D isdigit(c=tc())
		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
	public:
		I FastIO() {A=B=FI,C=FO,E=FO+FS;}
		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
		Tp I void writeln(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);pc('\n');}
		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
class ChairmanTree
{
	private:
		#define LT l,mid,O[x].S[0],O[y].S[0]
		#define RT mid+1,r,O[x].S[1],O[y].S[1]
		int Nt,Rt[N+5];struct node {int Sz,S[2];}O[N*LN+5];
		I void Ins(CI p,CI l,CI r,int& x,CI y)//插入一个数
		{
			if(++(O[x=++Nt]=O[y]).Sz,l==r) return;int mid=l+r>>1;
			p<=mid?Ins(p,LT):Ins(p,RT);
		}
		I int Qry(CI rk,CI l,CI r,CI x,CI y)//询问
		{
			if(l==r) return g[l];int mid=l+r>>1,t=O[O[y].S[0]].Sz-O[O[x].S[0]].Sz;
			return rk<=t?Qry(rk,LT):Qry(rk-t,RT);
		}
	public:
		I void Ins(CI v,CI x) {Ins(x,1,n,Rt[v],Rt[v-1]);}
		I int Qry(CI x,CI y) {return Qry(y,1,n,Rt[dI[x]-1],Rt[dO[x]]);}
}C;
I void dfs(CI x)//求出dfs序列
{
	f[dI[x]=++d]=x;for(RI i=lnk[x];i;i=e[i].nxt) !dI[e[i].to]&&(dfs(e[i].to),0);dO[x]=d;
}
I bool cmp(CI x,CI y) {return a[x]<a[y];}
int main()
{
	RI Qt,i,x,y;for(F.read(n),i=1;i<=n;++i) F.read(a[i]),g[i]=i;
	for(sort(g+1,g+n+1,cmp),i=1;i<=n;++i) a[g[i]]=i;//离散化(因为保证数各不同)
	for(i=1;i^n;++i) F.read(x),F.read(y),add(x,y),add(y,x);dfs(1);//连边dfs
	for(i=1;i<=n;++i) C.Ins(i,a[f[i]]);//插入元素
	F.read(Qt);W(Qt--) F.read(x),F.read(y),F.writeln(C.Qry(x,y));//处理询问
	return F.clear(),0;
}
posted @ 2020-05-28 09:33  TheLostWeak  阅读(130)  评论(0编辑  收藏  举报