彩虹评测喜提RE5 WA1 MLE3 AC2
提货码代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
const int N=1e5+10;
int n,m,r,mod,w[N]; //题中所给
int idx,h[N],e[N],ne[N]; //链式前向星相关
int dep[N],fa[N],size[N],son[N]; //dfs1相关
int cnt,id[N],wt[N],top[N]; //dfs2相关
int tree[N<<2],tag[N<<2]; //线段树相关
void add(int u,int v){ //链式前向星加边
idx++;
e[idx]=v;
ne[idx]=h[u];
h[u]=idx;
}
void pushdown(int rt,int l,int r){
if(!tag[rt]) return;
tag[ls]+=tag[rt];
tag[rs]+=tag[rt];
int mid=l+r>>1;
tree[ls]=(tree[ls]+tag[rt]*(mid-l+1))%mod;
tree[rs]=(tree[rs]+tag[rt]*(r-mid))%mod;
tag[rt]=0;
}
void build(int rt,int l,int r){ //线段树的建树操作
if(l==r){
tree[rt]=wt[l]%mod;
return;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
tree[rt]=(tree[ls]+tree[rs])%mod;
}
void upd(int rt,int l,int r,int L,int R,int v){
if(L<=l&&r<=R){
tag[rt]+=v;
tree[rt]+=v*(r-l+1);
return;
}
pushdown(rt,l,r);
int mid=l+r>>1;
if(L<=mid) upd(ls,l,mid,L,R,v);
if(R>mid) upd(rs,mid+1,r,L,R,v);
}
int query(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R) return tree[rt];
pushdown(rt,l,r);
int mid=l+r>>1,res=0;
if(L<=mid) res=(res+query(ls,l,mid,L,R))%mod;
if(R>mid) res=(res+query(rs,mid+1,r,L,R))%mod;
return res;
}
int queryRange(int x,int y){
int ans=0;
while(top[x]!=top[y]){ //不在一条链上
if(dep[top[x]]<dep[top[y]]) swap(x,y); //把x点改为所在链顶端的深度更深的那个点
ans=(ans+query(1,1,n,id[top[x]],id[x]))%mod; //ans加上x点到x所在链顶端 这一段区间的点权和
x=fa[top[x]]; //把x跳到x所在链顶端的那个点的上面一个点
}
if(dep[x]>dep[y]) swap(x,y); //x更深
ans=(ans+query(1,1,n,id[x],id[y]))%mod; //再加上此时两个点的区间和
return ans;
}
void updRange(int x,int y,int v){
v%=mod;
while(top[x]!=top[y]){ //同上
if(dep[top[x]<dep[top[y]]]) swap(x,y);
upd(1,1,n,id[top[x]],id[x],v);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
upd(1,1,n,id[x],id[y],v);
}
int querySon(int x){
return query(1,1,n,id[x],id[x]+size[x]-1); //子树区间右端点为id[x]+size[x]-1
}
void updSon(int x,int v){
upd(1,1,n,id[x],id[x]+size[x]-1,v);
}
void dfs1(int u,int f,int deep){ //当前节点,父亲和深度
dep[u]=deep;
fa[u]=f;
size[u]=1; // 标记深度、父亲和子树大小
int maxson=-1; //记录重儿子的儿子个数
for(int i=h[u];i;i=ne[i]){
int v=e[i];
if(v==f) continue;
dfs1(v,u,deep+1); //dfs其儿子
size[u]+=size[v];
if(size[v]>maxson){ //更新重儿子
maxson=size[v];
son[u]=v;
}
}
}
void dfs2(int u,int topf){ //当前节点和当前链最顶端的节点
id[u]=++cnt;
wt[cnt]=w[u];
top[u]=topf; //标记新编号、初始值和所在链顶端
if(!son[u]) return;
dfs2(son[u],topf); //先处理重儿子
for(int i=h[u];i;i=ne[i]){
int v=e[i];
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v); //再处理轻儿子
}
}
int main(){
scanf("%d %d %d %d",&n,&m,&r,&mod);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<=n-1;i++){
//建图
int a,b;
scanf("%d %d",&a,&b);
add(a,b);
add(b,a);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while(m--){
int op,x,y,z;
cin>>op;
if(op==1){
scanf("%d %d %d",&x,&y,&z);
updRange(x,y,z);
}else if(op==2){
scanf("%d %d",&x,&y);
printf("%d\n",queryRange(x,y));
}else if(op==3){
scanf("%d %d",&x,&y);
updSon(x,y);
}else{
scanf("%d",&x);
printf("%d\n",querySon(x));
}
}
return 0;
}
其中,如果把N定义为2e5+10会发生这样的事情: MLE->RE,不是很理解,题目给的范围是1e5啊,而且数组开大不是更占空间嘛