20pts自闭求助
查看原帖
20pts自闭求助
154999
huoxj_runz楼主2020/11/4 19:38

rt,只能过两个点

刚学oi要自闭了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define f(q,w,e) for(register int q=w;q<=e;++q) 
#define ff(q,w,e) for(register int q=w;q>=e;--q)
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs ((k<<1)|1)
#define xs double
#define lb(x) x&(-x)
const int N=4*1e5+5;
const int mod=571373;
inline ll w(){char c=getchar();ll ret=0,fs=1; while(c<'0'||c>'9'){if(c=='-') fs=-1;c=getchar();} while(c>='0'&&c<='9'){ret=(ret<<1)+(ret<<3)+c-'0';c=getchar();}return ret*fs;}


int n,T,p,root;
vector<int>e[N];

//==================线段树================================
int t[N],//线段树主体 
	tag[N],//加法标记 
	a[N];//按时间戳处理后的点权 
int ww[N];//原输入点权 

void build(int k,int l,int r){
	tag[k]=0;
	if(l==r){
		t[k]=a[l]%p;
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	t[k]=(t[ls]+t[rs])%p;
}

void pushdown(int k,int l,int r){
	if(!tag[k]) return;
	tag[ls]=(tag[ls]+tag[k])%p;
	tag[rs]=(tag[rs]+tag[k])%p;
	t[ls]=(t[ls]+tag[ls]*(mid-l+1))%p;
	t[rs]=(t[rs]+tag[k]*(r-mid))%p;
	tag[k]=0;
}

void modify(int k,int l,int r,int x,int y,int v){
	if(x<=l&&r<=y){
		tag[k]=(tag[k]+v)%p;
		t[k]=(t[k]+(r-l+1)*v)%p;
		return;
	}
	pushdown(k,l,r);
	if(x<=mid) modify(ls,l,mid,x,y,v);
	if(y>mid) modify(rs,mid+1,r,x,y,v);
	t[k]=(t[ls]+t[rs])%p;
}

int query(int k,int l,int r,int x,int y){
	if(l>y||x>r) return 0;
	if(x<=l&&r<=y){
		return t[k];
	}
	pushdown(k,l,r);
	int res=0;
	if(x<=mid) res=(res+query(ls,l,mid,x,y))%p;
	if(y>mid) res=(res+query(rs,mid+1,r,x,y))%p; 
	return res;
}

//=====================x线段树================================

int fa[N],// 
	sz[N],//子树大小 
	hs[N],//重儿子 
	dep[N];//深度 
void dfs1(int x,int ff,int depp){
	fa[x]=ff;dep[x]=depp;sz[x]=1;
	int maxs=-1;
	ff(i,e[x].size()-1,0){
		int to=e[x][i];
		if(to==ff) continue;
		dfs1(to,x,depp+1);
		sz[x]+=sz[to];
		if(sz[to]>maxs){
			hs[x]=to;maxs=sz[to];
		}
	}
}

int top[N],//重链顶端 
	dfn[N],//时间戳 
	tim=0;
void dfs2(int x,int Top){
	dfn[x]=++tim;top[x]=Top;
	a[tim]=ww[x];
	if(!hs[x]) return;
	dfs2(hs[x],Top);
	ff(i,e[x].size()-1,0){
		int to=e[x][i];
		if(to==fa[x]||to==hs[x]) continue;
		dfs2(to,to);
	}
}

void range_modify(int x,int y,int z){
	z%=p;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		modify(1,1,n,dfn[top[x]],dfn[x],z);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	modify(1,1,n,dfn[x],dfn[y],z);
}

int range_query(int x,int y){
	int res=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		res=(res+query(1,1,n,dfn[top[x]],dfn[x]))%p;
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	return (res+query(1,1,n,dfn[x],dfn[y]))%p;
}

void subtree_modify(int x,int z){
	z%=p;
	modify(1,1,n,dfn[x],dfn[x]+sz[x]-1,z);
}

int subtree_query(int x){
	return query(1,1,n,dfn[x],dfn[x]+sz[x]-1);
}

//======================================================

int main(){
	n=w(),T=w(),root=w(),p=w();
	f(i,1,n){//输入点权 
		ww[i]=w();
	}
	f(i,1,n-1){//输入边 
		int x=w(),y=w();
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dfs1(root,0,1);
	dfs2(root,root);
	build(1,1,n);
	while(T--){//输入操作 
		int op=w();
		if(op==1){//两点修改 
			int x=w(),y=w(),z=w();
			range_modify(x,y,z);
		}
		if(op==2){//两点查询  
			int x=w(),y=w();
			printf("%d\n",range_query(x,y));
		
		}
		if(op==3){//子树修改 
			int x=w(),z=w();
			subtree_modify(x,z);
		}
		if(op==4){//子树查询 
			int x=w();
			printf("%d\n",subtree_query(x));
		}
	}
}

2020/11/4 19:38
加载中...