[BZOJ1146][樹套樹][樹鏈剖分]CTSC2008:網絡管理

鏈接自己找,BZOJ還沒開

題意:求樹上路徑第k大,單點修改,可離線

考慮樹剖維護,內層主席樹外層套個樹狀數組就完了(時空和代碼長度都全方位被整體二分吊打)
也可以整體二分

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=8e4+5;
int sign[500],tmp[500],tot=0;
int b[N<<1];
namespace president_tree{
	struct seg{int l,r,sz;}tr[N*200];int cnt=0;
	#define ls(k) tr[k].l
	#define rs(k) tr[k].r
	#define mid (l+r>>1)
	inline void ins(int &rt,int l,int r,int pos,int v){
		tr[++cnt]=tr[rt];tr[cnt].sz+=v;rt=cnt;
		if(l==r) return;
		if(pos<=mid) ins(ls(rt),l,mid,pos,v);
		else ins(rs(rt),mid+1,r,pos,v);
	}
	inline int query(int l,int r,int k){
		if(l==r) return l;
		int sum=0;
		for(int i=1;i<=tot;i++) sum+=tr[rs(tmp[i])].sz*sign[i];
		if(k<=sum){
			for(int i=1;i<=tot;i++) tmp[i]=rs(tmp[i]);
			return query(mid+1,r,k);
		}
		else{
			for(int i=1;i<=tot;i++) tmp[i]=ls(tmp[i]);
			return query(l,mid,k-sum);	
		}
	}
}
using president_tree::ins;
using president_tree::query;
int n,nn;
int rt[N];
namespace Bit{
	inline int lb(int x){return x&(-x);}
	inline void add(int x,int pos,int v){for(int i=x;i<=n;i+=lb(i)) ins(rt[i],1,nn,pos,v);}
	inline void mark(int x,int v){for(int i=x;i;i-=lb(i)) tmp[++tot]=rt[i],sign[tot]=v;}
}
using Bit::mark;
namespace treecut{
	int vis[N<<1],head[N],nxt[N<<1],etot=0;
	inline void add(int x,int y){vis[++etot]=y;nxt[etot]=head[x];head[x]=etot;}
	int siz[N],hson[N],dep[N],fa[N];
	void dfs1(int v){
		siz[v]=1;
		for(int i=head[v];i;i=nxt[i]){
			int y=vis[i];
			if(y==fa[v]) continue;
			fa[y]=v;dep[y]=dep[v]+1;
			dfs1(y);
			siz[v]+=siz[y];
			if(siz[y]>siz[hson[v]]) hson[v]=y;
		}
	}
	int top[N],dfn[N],sign=0,id[N];
	void dfs2(int v){
		dfn[v]=++sign;id[sign]=v;
		if(hson[v]) top[hson[v]]=top[v],dfs2(hson[v]);
		for(int i=head[v];i;i=nxt[i])
			if(!top[vis[i]]) top[vis[i]]=vis[i],dfs2(vis[i]);
	}
	inline void query_path(int x,int y,int k){
		tot=0;int cur=dep[x]+dep[y]+1;
		while(top[x]!=top[y]){
			if(dep[top[x]]<dep[top[y]]) swap(x,y);
			mark(dfn[top[x]]-1,-1);mark(dfn[x],1);x=fa[top[x]];
		}
		if(dep[x]<dep[y]) swap(x,y);
		mark(dfn[y]-1,-1);mark(dfn[x],1);
		cur-=2*dep[y];
		if(cur<k) puts("invalid request!");
		else cout<<b[query(1,nn,k)]<<"\n";
	}
}
using namespace treecut;
int val[N];
struct Q{int k,a,b;}q[N];
int main(){
	nn=n=read();int m=read();
	for(int i=1;i<=n;i++) val[i]=b[i]=read();
	for(int x,y,i=1;i<n;i++){
		x=read(),y=read();
		add(x,y);add(y,x);
	}
	for(int i=1;i<=m;i++){
		q[i].k=read(),q[i].a=read(),q[i].b=read();
		if(!q[i].k) b[++nn]=q[i].b;
	}
	sort(b+1,b+nn+1);
	nn=unique(b+1,b+nn+1)-b-1;
	for(int i=1;i<=n;i++) val[i]=lower_bound(b+1,b+nn+1,val[i])-b;
	for(int i=1;i<=m;i++) if(!q[i].k) q[i].b=lower_bound(b+1,b+nn+1,q[i].b)-b;
	dep[1]=1;dfs1(1);top[1]=1;dfs2(1);
	for(int i=1;i<=n;i++) Bit::add(i,val[id[i]],1);
	for(int i=1;i<=m;i++){
		if(!q[i].k){
			Bit::add(dfn[q[i].a],val[q[i].a],-1);
			Bit::add(dfn[q[i].a],q[i].b,1);
			val[q[i].a]=q[i].b;
		}
		else query_path(q[i].a,q[i].b,q[i].k);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章