Kth-> Chairman Tree

Write a summary of the learning content of the last three days ...

Actually I feel that I can finish it in one day, but recently I have to take liver culture class

\ (1. \) Chairman tree \ (\ rightarrow \) section \ (k \) is the largest, or the relevant content of the line tree can be persisted

\ (2. \) The tree chain is the largest \ (k \)

\ (3. \) is the largest with repair interval \ (k \)

\ (4. \) with repair tree chain \ (k \) large

The last two are actually tree sets (tree-like array set of chairman trees)

principle

Our principle is to use the chairman tree to maintain the prefix and

Now we have a modification operation. If we simply modify the \ (n \) prefix chairman tree, query the prefix and

The complexity is too high, which is unacceptable to us

Then we consider turning to maintaining the position of the chairman tree with a tree-like array, and maintaining and modifying and querying on the marker

In this way, the complexity is \ (O (nlog ^ 2n) \) every time we modify , the query is the same

Attach a series of practices on the tree:

Similar to \ (p = rt [i], pre = rt [i-1] \) on the interval

Here we replace: \ (p = rt [x], pre = rt [fa [x]] \)

Just update it as before, then here is the difference on the tree when querying

Don't be dizzy, every tree here is a weighted line segment tree

int lca=lca(x,y)'s node ,f_l=fa[lca(x,y)]'s node
sum=val(ls[x])+val(ls[y])-val(lca)-val(ls(f_l))

Pseudo code

Then for this big board with repair tree chain \ (k \) : P4175 [CTSC2008] network management

Found that the modification of each point has an impact on the subtree

So this is an interval change, single check

Difference! It becomes an interval check, single point plus

Then maintain a \ (dfn \) sequence on the tree array \ (OK \)

This is quite understandable, but the size of the hand, the hand is not easy to adjust (the blogger has not adjusted the hand too long this time)

In fact: we can learn the writing of this big guy while jumping \ (ls \) or \ (rs \) , which can reduce the amount of code:

https://www.luogu.com.cn/blog/jiqimao/p4175-ti-xie

After I finished writing, I found that there is still a way to write structure.

Finally put the stinky and long \ (Code: \)

#include<bits/stdc++.h>
using namespace std;
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar();
 		return res*f;
	}
	const int N=80000+10;
	inline int lowbit(int x){return x&(-x);}
	vector<int> g[N];
	int fa[N][20],lg[N],dep[N],b[N<<1],m,T,in[N],out[N];
	struct node{
		int id,k,x,y,val,opt;
	}q[N];
	int c1,c2,c3,c4,t1[30],tim,t2[30],t3[30],t4[30],n,p[N];
	struct tree{
		int ls,rs,val;
		#define ls(p) t[p].ls
		#define rs(p) t[p].rs
		#define val(p) t[p].val
	}t[20000010];
	int rt[N<<2],tot;
	inline void push_up(int p){return val(p)=val(ls(p))+val(rs(p)),void();}
	inline void update(int &p,int l,int r,int x,int v)
	{
		if(!p) p=++tot;
		if(l==r) return val(p)+=v,void();
		int mid=(l+r)>>1;
		if(x<=mid) update(ls(p),l,mid,x,v);
		else update(rs(p),mid+1,r,x,v);
		return push_up(p);
	}
	inline int query(int l,int r,int k)
	{
		if(l==r) return l;
		int mid=(l+r)>>1,sum=0;
		for(int i=1;i<=c3;++i) sum+=val(rs(t3[i]));
		for(int i=1;i<=c4;++i) sum+=val(rs(t4[i]));
		for(int i=1;i<=c2;++i) sum-=val(rs(t2[i]));
		for(int i=1;i<=c1;++i) sum-=val(rs(t1[i]));
		if(k>sum)
		{
			for(int i=1;i<=c1;++i) t1[i]=ls(t1[i]);
			for(int i=1;i<=c2;++i) t2[i]=ls(t2[i]);
			for(int i=1;i<=c3;++i) t3[i]=ls(t3[i]);
			for(int i=1;i<=c4;++i) t4[i]=ls(t4[i]);
			return query(l,mid,k-sum);
		}
		else
		{
			for(int i=1;i<=c1;++i) t1[i]=rs(t1[i]);
			for(int i=1;i<=c2;++i) t2[i]=rs(t2[i]);
			for(int i=1;i<=c3;++i) t3[i]=rs(t3[i]);
			for(int i=1;i<=c4;++i) t4[i]=rs(t4[i]);
			return query(mid+1,r,k);
		}
	}
	inline int lca(int x,int y)
	{
		if(dep[x]<dep[y]) swap(x,y);
		while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]-1];
		if(x==y) return x;
		for(int i=19;i>=0;--i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
		return fa[x][0];
	}
	inline int ask(int x,int y,int k)
	{
		c1=0,c2=0,c3=0,c4=0; 
		int l=lca(x,y);
		for(int i=in[fa[l][0]];i;i-=lowbit(i)) t1[++c1]=rt[i];
		for(int i=in[l];i;i-=lowbit(i)) t2[++c2]=rt[i];
		for(int i=in[x];i;i-=lowbit(i)) t3[++c3]=rt[i];
		for(int i=in[y];i;i-=lowbit(i)) t4[++c4]=rt[i];
		return query(1,m,k);
	}
	inline void dfs(int x,int fat)
	{
		dep[x]=dep[fat]+1; fa[x][0]=fat; in[x]=++tim; 
		for(int i=1;(1<<i)<=dep[x];++i) fa[x][i]=fa[fa[x][i-1]][i-1];
		int siz=g[x].size();
		for(int i=0;i<siz;++i) if(g[x][i]!=fat) dfs(g[x][i],x);
		return out[x]=tim,void();
	}
	
	inline void change(int x,int pos,int val)
	{
		for(int i=x;i<=n;i+=lowbit(i)) update(rt[i],1,m,pos,val);
		return ;
	}
	signed main()
	{
		for(int i=1;i<N;++i) lg[i]=lg[i-1]+((1<<lg[i-1])==i);
		n=read(); T=read();
		for(int i=1;i<=n;++i) p[i]=read(),b[++m]=p[i];
		for(int i=1;i<n;++i) 
		{
			int u=read(),v=read();
			g[u].push_back(v); g[v].push_back(u); 
		}
		for(int i=1;i<=T;++i)
		{
			q[i].opt=read();
			if(q[i].opt) q[i].x=read(),q[i].y=read(),q[i].k=q[i].opt;
			else q[i].id=read(),q[i].val=read(),b[++m]=q[i].val;
		}
		sort(b+1,b+m+1); m=unique(b+1,b+m+1)-b-1;
		for(int i=1;i<=n;++i) p[i]=lower_bound(b+1,b+m+1,p[i])-b;
		for(int i=1;i<=T;++i) if(!q[i].opt) q[i].val=lower_bound(b+1,b+m+1,q[i].val)-b;
		dfs(1,0);
		for(int i=1;i<=n;++i) change(in[i],p[i],1),change(out[i]+1,p[i],-1);
		for(int i=1;i<=T;++i)
		{
			if(q[i].opt) 
			{
				int l=lca(q[i].x,q[i].y);
				if(dep[q[i].x]+dep[q[i].y]-dep[l]*2+1<q[i].k) puts("invalid request!");
				else printf("%d\n",b[ask(q[i].x,q[i].y,q[i].k)]);
			}
			else
			{
				change(in[q[i].id],p[q[i].id],-1),change(out[q[i].id]+1,p[q[i].id],1);
				p[q[i].id]=q[i].val;
				change(in[q[i].id],p[q[i].id],1); change(out[q[i].id]+1,p[q[i].id],-1);
			}
		}
		return 0;
	}
}
signed main(){return yspm::main();}

It ’s because it ’s all a board, so I learned this. The line tree set balance tree does n’t work. \ (2444 \)

Guess you like

Origin www.cnblogs.com/yspm/p/12707658.html