求助
查看原帖
求助
300370
flyfreemrn楼主2025/1/4 10:47

MnZn自学淀粉树RE了6个点WA#3

using namespace std;
#define ll int
#define MAXN 200010
// By flyfreemrn
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
inline void write(ll x){
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
struct node_sgt{//动态开点权值线段树 
	ll idx,sum[MAXN*50],son[MAXN*50][2];
	stack <ll> st;
	ll newnode(){
		ll now;
		if(!st.empty())now=st.top(),st.pop();
		else now=++idx;
		sum[now]=son[now][0]=son[now][1]=0;
		return now;
	}
	void insert(ll &now,ll pos,ll val,ll l,ll r){
		if(!now)now=newnode();
		sum[now]+=val;
//		cout<<"insert: "<<now<<" "<<l<<" "<<r<<" "<<sum[now]<<endl;
		if(l==r){
			if(!sum[now]){
				st.push(now);
				now=0;
			}
			return;
		}
		ll mid=(l+r)/2;
		if(pos<=mid)insert(son[now][0],pos,val,l,mid);
		else insert(son[now][1],pos,val,mid+1,r);
		if(!sum[now]){
			st.push(now);
			now=0;
		}
		return;
	}
	ll find(ll now,ll dl,ll dr,ll l,ll r){
		if(!now)return 0;
		if(l>=dl&&r<=dr)return sum[now];
		ll ans=0,mid=(l+r)/2;
		if(dl<=mid)ans+=find(son[now][0],dl,dr,l,mid);
		if(dr>mid)ans+=find(son[now][1],dl,dr,mid+1,r);
		return ans;
	}
}sgt;
bool used[MAXN];
ll n,m,idx;
ll val[MAXN],dep[MAXN];
ll hd[MAXN],ed[MAXN*2],nxt[MAXN*2];
ll p[MAXN][50];
void build(ll x,ll y){
	nxt[++idx]=hd[x];
	ed[idx]=y;
	hd[x]=idx;
}
void dfs1(ll now){//dfs预处理 
	dep[now]=dep[p[now][0]]+1;
	for(int i=1;i<=30;i++)p[now][i]=p[p[now][i-1]][i-1];
	for(int i=hd[now];i;i=nxt[i]){
		ll y=ed[i];
		if(y==p[now][0])continue;
		p[y][0]=now;
		dfs1(y);
	}
}
ll get_len(ll x,ll y){//求树上两点距离 
	ll len=0;
	if(dep[x]<dep[y])swap(x,y);
	for(int i=30;i>=0;i--){
		if(dep[p[x][i]]>=dep[y]){
			x=p[x][i];
			len+=(1<<i);
		}
	}
	if(x==y)return len;
	for(int i=30;i>=0;i--){
		if(p[x][i]!=p[y][i]){
			x=p[x][i],y=p[y][i];
			len+=(1<<i+1);
		}
	}
	return len+2;
}
struct Pt{
	bool used[MAXN];
	ll siz[MAXN],min_siz,min_id;
	void get_siz(ll now,ll fa){//处理子树大小 
		siz[now]=1;
		for(int i=hd[now];i;i=nxt[i]){
			ll y=ed[i];
			if(used[y]||y==fa)continue;
			get_siz(y,now);
			siz[now]+=siz[y];
		}
	}
	void get_rot(ll now,ll fa,ll tot){//查找重心 
		ll mxu=tot-siz[now];
		for(int i=hd[now];i;i=nxt[i]){
			ll y=ed[i];
			if(used[y]||y==p[now][0])continue;
			get_rot(y,now,tot);
			mxu=max(mxu,siz[y]);
		}
		if(mxu<min_siz)min_siz=mxu,min_id=now;
	}
	ll fa[MAXN],id[MAXN],rot[MAXN];
	vector<ll> son[MAXN],rot_son[MAXN];
	void add(ll now,ll _fa,ll &_rot1,ll &_rot2,ll _dep){//递归加点 
//		cout<<now<<" "<<_dep<<" "<<val[now]<<endl;
		sgt.insert(_rot1,_dep,val[now],0,n);
		sgt.insert(_rot2,_dep,val[now],0,n);
		for(int i=hd[now];i;i=nxt[i]){
			ll y=ed[i];
			if(used[y]||y==_fa)continue;
			add(y,now,_rot1,_rot2,_dep+1);
		}
	}
	void solve(ll now){//点分治建树 
		used[now]=true;
		sgt.insert(rot[now],0,val[now],0,n);
		for(int i=hd[now];i;i=nxt[i]){
			ll y=ed[i];
			if(used[y])continue;
			rot_son[now].push_back(0);
			add(y,now,rot[now],rot_son[now][rot_son[now].size()-1],1);
			//处理子树点权 
			get_siz(y,now);
			min_siz=siz[y],min_id=y;
			get_rot(y,now,siz[y]);
			//处理子树y的重心 
			fa[min_id]=now,id[min_id]=son[now].size();
			son[now].push_back(min_id);
			//处理点分树信息 
		}
//		cout<<"solve: "<<now<<" ";
//		for(int i=0;i<son[now].size();i++)cout<<son[now][i]<<" ";
//		cout<<endl;
		for(int i=0;i<son[now].size();i++){//淀粉汁 
			ll y=son[now][i];
			solve(y);
		}
//		used[now]=true;
	}
	void change(ll pos,ll new_val,ll re_val){
		sgt.insert(rot[pos],0,-re_val,0,n);
		sgt.insert(rot[pos],0,new_val,0,n);
		//当前位置更新 
		ll x=fa[pos],_id=id[pos];
		while(x){
			ll _len=get_len(x,pos);
			sgt.insert(rot[x],_len,-re_val,0,n);
			sgt.insert(rot[x],_len,new_val,0,n);
			sgt.insert(rot_son[x][_id],_len,-re_val,0,n);
			sgt.insert(rot_son[x][_id],_len,new_val,0,n);
			_id=id[x],x=fa[x];
			//跳重心更新祖先 
		}
	}
	ll find(ll pos,ll k){
		ll ans=0;
		ans+=sgt.find(rot[pos],0,k,0,n);
//		cout<<pos<<" "<<ans<<endl;
		ll x=fa[pos],_id=id[pos];
		while(x){
			ll _len=get_len(x,pos);
			if(_len>k)break;
			ans+=sgt.find(rot[x],0,min(n,k-_len),0,n);
			ans-=sgt.find(rot_son[x][_id],0,min(n,k-_len),0,n);
			_id=id[x],x=fa[x];
		} 
		return ans;
	}
}Pt;
ll _ans;
int main(){
//	freopen("P6329_1.in","r",stdin);
	n=read(),m=read();
	for(int i=1;i<=n;i++)val[i]=read();
	for(int i=1;i<n;i++){
		ll x=read(),y=read();
		build(x,y);
		build(y,x);
	}
	dfs1(1);
	Pt.get_siz(1,0);
	Pt.min_siz=1e9,Pt.min_id=0;
	Pt.get_rot(1,0,Pt.siz[1]);
	Pt.solve(Pt.min_id);
	for(int i=1;i<=m;i++){
		ll type=read();
		if(type==0){
			ll x=read(),k=read();
			cout<<(_ans=Pt.find(x,k))<<endl;
		}else{
			ll x=read(),y=read();
			Pt.change(x,y,val[x]);
			val[x]=y;
		}
	}
	return 0;
}
2025/1/4 10:47
加载中...