MLE 73 求调
查看原帖
MLE 73 求调
882043
continueOI喵呜ˆωˆ楼主2023/11/18 12:29

link

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,root,mod,op,x,y,k;
int deep[N];//节点的深度 
int fa[N];//节点的父亲 
int son[N];//节点的重儿子 
int tot[N];//节点子树的大小 
int top[N];//重链的头 
int idx[N],cnt;//重新编号 
int b[N],a[N];
struct node{
    int u,v,nxt;
}edge[N];
int head[N];
int num=1;
inline void add_edge(int x,int y){
    edge[num].u=x;
    edge[num].v=y;
    edge[num].nxt=head[x];
    head[x]=num++;
}
//以下是线段树 
int w[N*4],wl[N*4],wr[N*4],lzy[N*4];
void pushup(int u){
	w[u]=(w[u*2]+w[u*2+1])%mod;
}
void build(int u,int l,int r){
	wl[u]=l,wr[u]=r;
	if(l==r){
		w[u]=a[l]%mod;
		return;
	}
	int mid=(l+r)/2;
	build(u*2,l,mid),build(u*2+1,mid+1,r);
	pushup(u);
}
void maketag(int u,int len,int x){
	lzy[u]+=x;
	w[u]+=x*len;
	lzy[u]%=mod,w[u]%=mod;
}
void pushdown(int u,int l,int r){
	int mid=(l+r)/2;
	maketag(u*2,mid-l+1,lzy[u]);
	maketag(u*2+1,r-mid,lzy[u]);
	lzy[u]=0;
}
bool InRange(int L,int R,int l,int r){
	return (L<=l)&&(R>=r);
}
bool OutofRange(int L,int R,int l,int r){
	return (l>R)||(r<L);
}
int query(int u,int l,int r,int L,int R){
	if(InRange(L,R,l,r)) return w[u];
	else if(!OutofRange(L,R,l,r)){
		int mid=(l+r)/2;
		pushdown(u,l,r);
		return (query(u*2,l,mid,L,R)+query(u*2+1,mid+1,r,L,R))%mod;
	}else return 0;
}
void update(int u,int l,int r,int L,int R,int x){
	if(InRange(L,R,l,r)) maketag(u,r-l+1,x);
	else if(!OutofRange(L,R,l,r)){
		int mid=(l+r)/2;
		pushdown(u,l,r);
		update(u*2,l,mid,L,R,x);
		update(u*2+1,mid+1,r,L,R,x);
		pushup(u);
	}
}
//以上是线段树 
int dfs1(int now,int f,int dep){
    deep[now]=dep;
    fa[now]=f;
    tot[now]=1;
    int maxson=-1;
    for(int i=head[now];i!=-1;i=edge[i].nxt){
        if(edge[i].v==f) continue;
        tot[now]+=dfs1(edge[i].v,now,dep+1);
        if(tot[edge[i].v]>maxson)
			maxson=tot[edge[i].v],son[now]=edge[i].v;
    }
    return tot[now];
}
void dfs2(int now,int topf){//topf是u所在重链的顶端节点
    idx[now]=++cnt;
    a[cnt]=b[now];
    top[now]=topf;
    if(!son[now]) return;
    dfs2(son[now],topf);
    for(int i=head[now];i!=-1;i=edge[i].nxt)
        if(!idx[edge[i].v])
            dfs2(edge[i].v,edge[i].v);
}
int tree_sum(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        ans=(ans+query(1,1,n,idx[top[x]],idx[x]))%mod;
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    ans=(ans+query(1,1,n,idx[x],idx[y]))%mod;
    return ans;
}
void tree_add(int x,int y,int val){
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        update(1,1,n,idx[top[x]],idx[x],val);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    update(1,1,n,idx[x],idx[y],val);
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m>>root>>mod;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1,x,y;i<=n-1;i++){
		cin>>x>>y;
		add_edge(x,y),add_edge(y,x);
	}
	dfs1(root,0,1);
    dfs2(root,root);
	build(1,1,n);
	while(m--){
		cin>>op;
        if(op==1){    
        	cin>>x>>y>>k;
            tree_add(x,y,k%mod);
        }
        if(op==2){
            cin>>x>>y;
            cout<<tree_sum(x,y)<<'\n';
        }
        if(op==3){
            cin>>x>>k;
            update(1,1,n,idx[x],idx[x]+tot[x]-1,k%mod);
        }
        if(op==4){
            cin>>x;
            cout<<query(1,1,n,idx[x],idx[x]+tot[x]-1)<<'\n';
        }
    }
	return 0;
}
2023/11/18 12:29
加载中...