[SYZOJ279]滑♂稽♂树

主♂席♂树♂裸♂题

https://syzoj.com/problem/279

https://oj.changjun.com.cn/problem/detail/pid/2425

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#define il inline
#define rg register
#define vd void
#define sta static
typedef long long ll;
il int gi(){
	rg int x=0,f=1;rg char ch=getchar();
	while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
const int _=30001;
int n,w[_],dfn[_],ed[_];
namespace cmt{
#define mid ((l+r)>>1)
	typedef const int& ci;
	const int __=_*100;
	int index,rt[10001],ls[__],rs[__],sum[__];
	il vd update(int&x,int l,int r,ci o,ci p){
		if(!x)x=++index;sum[x]+=o;
		if(l==r)return;
		if(p<=mid)update(ls[x],l,mid,o,p);
		else update(rs[x],mid+1,r,o,p);
	}
	il vd Update(int x,int p,int o){for(rg int i=p;i<=10000;i+=i&-i)update(rt[i],1,n,o,x);}
	il int query(int x,int l,int r,int L,int R){
		if(!sum[x])return 0;
		if(L<=l&&r<=R)return sum[x];
		if(L<=mid)
			if(mid<R)return query(ls[x],l,mid,L,R)+query(rs[x],mid+1,r,L,R);
			else return query(ls[x],l,mid,L,R);
		else return query(rs[x],mid+1,r,L,R);
	}
	il int Query(int a,int b,int l,int r){
		int ret=0;
		for(rg int i=b;i;i-=i&-i)ret+=query(rt[i],1,n,l,r);
		for(rg int i=a-1;i;i-=i&-i)ret-=query(rt[i],1,n,l,r);
		//printf("%d %d %d %d %d\n",a,b,l,r,ret);
		return ret;
	}
#undef mid
}
namespace tree{
	int fir[_],nxt[_*2],dis[_*2];
	il vd link(int x,int y){
		sta int id;
		nxt[++id]=fir[x],fir[x]=id,dis[id]=y;
		nxt[++id]=fir[y],fir[y]=id,dis[id]=x;
	}
	il vd dfs(int x,int fa=-1){
		dfn[x]=++dfn[0];
		for(int i=fir[x];i;i=nxt[i])
			if(fa!=dis[i])dfs(dis[i],x);
		ed[x]=dfn[0];
	}
	il vd prepare(){
		dfs(1);
		for(rg int i=1;i<=n;++i)cmt::Update(dfn[i],w[i],1);
	}
}
int main(){
	#ifdef xzz
	freopen("huaji.in","r",stdin);
	freopen("huaji.out","w",stdout);
	#endif
	n=gi();
	for(rg int i=1;i<=n;++i)w[i]=gi();
	for(rg int i=1;i<n;++i)tree::link(gi(),gi());
	tree::prepare();
	int q=gi(),o,a,b,u;
	while(q--){
		o=gi();
		if(o==1){
			u=gi(),a=gi();
			int l=1,r=10000,mid;
			while(l<r){
				mid=(l+r)>>1;
				if(cmt::Query(1,mid,dfn[u],ed[u])<a)l=mid+1;
				else r=mid;
			}
			printf("%d\n",l);
		}else if(o==2){
			u=gi(),a=gi(),b=gi();
			printf("%d\n",cmt::Query(a,b,dfn[u],ed[u]));
		}else if(o==3){
			u=gi(),a=gi();
			cmt::Update(dfn[u],w[u],-1);
			cmt::Update(dfn[u],w[u]=a,1);
		}else puts("FA♂Q");
	}
	return 0;
}
posted @ 2018-03-15 15:03  菜狗xzz  阅读(209)  评论(0编辑  收藏  举报