求助,90AC,最后一个点RE
查看原帖
求助,90AC,最后一个点RE
296595
Matutino_Lux楼主2021/5/14 21:54

#include<bits/stdc++.h>
#define INF 0x7fffffff
#define ll long long
using namespace std;

ll read(){
	ll k=1,x=0;char ch=getchar(); 
	while (ch<'0'||ch>'9') {if (ch=='-') k=-1; ch=getchar();}
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
	return k*x;
}

const int N=3e5+10;
struct EDGE{
	ll to,pre;
}edge[N];
ll a[N],size[N],fa[N],dep[N],id[N],w[N],son[N],top[N],head[N];
ll cnt,mod,n,m,r;

//================== 以下为线段树模板 ====================
#define up(x) t[x].sum=t[x<<1].sum+t[x<<1|1].sum 
struct node{
	ll l,r;
	ll sum,lazy;
}t[N<<2];
ll len(ll p){
	return t[p].r-t[p].l+1;
}
void brush(ll p,ll k){
	t[p].lazy+=k%mod;
	t[p].sum+=len(p)*k%mod;
} 
void push_down(ll p){
	brush(p<<1,t[p].lazy);
    brush(p<<1|1,t[p].lazy);
	t[p].lazy=0;	
} 
void build(ll p,ll l,ll r){
	t[p].l=l;t[p].r=r;
	if (l==r){
		t[p].sum=w[l];return; 
	}
	ll mid=l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r); 
	up(p);
}
void update(ll p,ll l,ll r,ll k){
	if (t[p].l>=l&&t[p].r<=r){
		brush(p,k);
		return;
	}
	push_down(p);
	ll mid=t[p].l+t[p].r>>1;
	if (mid>=l) update(p<<1,l,r,k);
	if (r>=mid+1) update(p<<1|1,l,r,k);
	up(p); 	
} 
ll getans(ll p,ll l,ll r){
	if (t[p].l>=l&&t[p].r<=r)
		return t[p].sum;
	push_down(p);
	ll ans=0;
	ll mid=t[p].l+t[p].r>>1;
	if (l<=mid) ans+=getans(p<<1,l,r);
	if (r>=mid+1) ans+=getans(p<<1|1,l,r);
	return ans%mod; 
} 
//================== 以上为线段树模板 ==================== 


//================== 以下为树剖操作模板 ==================== 
inline void updatetree(ll s,ll t,ll c){ //s到t的简单路径加上c 
	while (top[s]!=top[t]){ //倍增思想,深度大的往上跳 
		if (dep[top[s]]>dep[top[t]]) swap(s,t); //默认t深度大 
		update(1,id[top[t]],id[t],c); //先维护这一段链 
		t=fa[top[t]]; //跳到这个链头的父节点,维护下一个链 
	}
	if (dep[s]>dep[t]) swap(s,t); //默认t深度大 
	update(1,id[s],id[t],c); //维护s与现在t(同深度)的链 
} 
inline ll getanstree(ll s,ll t){ //查询s到t的简单路径权值和 
    ll ans=0;
	while (top[s]!=top[t]){ //倍增思想,深度大的往上跳 
		if (dep[top[s]]>dep[top[t]]) swap(s,t); //默认t深度大 
		ans+=getans(1,id[top[t]],id[t]); //先查询这一段链 
		t=fa[top[t]]; //跳到这个链头的父节点,查询下一个链 
	}
	if (dep[s]>dep[t]) swap(s,t); //默认t深度大 
	ans+=getans(1,id[s],id[t]); //查询s与现在t(同深度)的链 
	return ans%mod;
} 
inline void updateson(ll x,ll t){ //以x为根的子树加上t 
	update(1,id[x],id[x]+size[x]-1,t);
}
inline ll getansson(ll x){ //查询以x为根的子树权值和 
	return getans(1,id[x],id[x]+size[x]-1)%mod;
}
//================== 以上为树剖操作模板 ==================== 

//================== 以下为dfs ==================== 
inline void dfs1(ll x,ll fath,ll deep){
    dep[x]=deep;        
    fa[x]=fath;           
    size[x]=1;             
    ll maxson=-1;         
    for(ll i=head[x];i;i=edge[i].pre){
        ll y=edge[i].to;
        if(y==fath) continue;
        dfs1(y,x,deep+1);
        size[x]+=size[y];   
        if(size[y]>maxson){ 
		    son[x]=y;
			maxson=size[y];
		}                    
    }
}

ll tim; 
inline void dfs2(ll x,ll fst){
    id[x]=++tim;         
    w[tim]=a[x];          
    top[x]=fst;           
    if(!son[x])return;    
    dfs2(son[x],fst);     
    for(ll i=head[x];i;i=edge[i].pre){
        ll y=edge[i].to;
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);        
    }
}
//================== 以上为dfs ====================
 
inline void add(ll u,ll v){ //链式前向星 
	edge[++cnt].pre=head[u];
	edge[cnt].to=v;
	head[u]=cnt;
}

int main(){
	freopen("in.in","r",stdin) ;
//	freopen("in.out","w",stdout) ;
    n=read();m=read();r=read();mod=read(); 
    for(ll i=1;i<=n;i++) a[i]=read()%mod;
    for(ll i=1;i<n;i++){
        ll a,b;
        a=read();b=read();
        add(a,b);add(b,a);
    }
    dfs1(r,0,1);
    dfs2(r,r);
    build(1,1,n);
    
	for (ll i=1;i<=m;i++){
		ll opt=read(),x=read();
		if (opt==1){
			ll y=read(),z=read()%mod;
			updatetree(x,y,z);
			
		}
		if (opt==2){
			ll y=read()%mod;
			cout<<getanstree(x,y)<<endl;
		}
		if (opt==3){
			ll z=read()%mod;
			updateson(x,z);
		}
		if (opt==4) cout<<getansson(x)<<endl;
	} 
	return 0;
}


2021/5/14 21:54
加载中...