Luogu4175 [CTSC2008]网络管理

Solution

发现每个点的修改是对子树有影响的,所以这是个区间改,单点查,所以考虑差分,转化为区间查,单点加

使用主席树维护第 (k) 大,接着上树状数组维护 (dfn) 序即可

实现的时候可以参考下方链接里面的内容来减少码量

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

(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
",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();}
原文地址:https://www.cnblogs.com/yspm/p/12707658.html