P3384:https://www.luogu.org/problemnew/show/P3384
ac:
#include<bits/stdc++.h>
#define ls l,m,rt
#define rs m+1,r,rt
#define ll long long
#define MAXN 400005
using namespace std;
int to[MAXN],next1[MAXN],head[MAXN];
int p[MAXN];
int n,m,r,a,b,tot=0,tim=0,x,v;
int top[MAXN],dep[MAXN];
int f[MAXN],son[MAXN];
int siz[MAXN];
int id[MAXN],w[MAXN];
int mod;
/***********************线段树部分*/
int sum[MAXN<<2],add2[MAXN<<2];
void pushup(int rt){
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;
}
void pushdown(int rt,int ln,int rn){
if(add2[rt]){
add2[rt<<1]+=add2[rt];
add2[rt<<1|1]+=add2[rt];
sum[rt<<1]+=(add2[rt]*ln)%mod;
sum[rt<<1|1]+=(add2[rt]*rn)%mod;
sum[rt<<1]%=mod;
sum[rt<<1|1]%=mod;
add2[rt]=0;
}
}
void build(int l,int r,int rt){
if(l==r) {
sum[rt]=w[l];
sum[rt]=sum[rt]%mod;
return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(int L,int R,int C,int l,int r,int rt){
if(L<=l&&R>=r){
sum[rt]+=(r-l+1)*C;
sum[rt]=sum[rt]%mod;
add2[rt]+=C;
return;
}
int m=(l+r)>>1;
if(add2[rt])
pushdown(rt,m-l+1,r-m);
if(L<=m) update(L,R,C,l,m,rt<<1);
if(R>m) update(L,R,C,m+1,r,rt<<1|1);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r) return sum[rt];
int m=(l+r)>>1;
if(add2[rt])
pushdown(rt,m-l+1,r-m);
int ans=0;
if(L<=m) ans+=query(L,R,l,m,rt<<1);
ans=ans%mod;
if(R>m) ans+=query(L,R,m+1,r,rt<<1|1);
ans=ans%mod;
return ans;
}
/************************/
void add(int u,int v)
{
to[++tot]=v;
next1[tot]=head[u];
head[u]=tot;
}
void dfs1(int x,int fa,int deep)
{
f[x]=fa;//父节点
dep[x]=deep;//深度
siz[x]=1;//子树大小
int maxson=-1;
for(int i=head[x];i;i=next1[i])
{
int v=to[i];
if(v==fa)
continue;
dfs1(v,x,deep+1);
siz[x]+=siz[v];
if(siz[v]>maxson)
{
maxson=siz[v];
son[x]=v;//重儿子
}
}
}
void dfs2(int x,int fst)//节点,节点最上边的点
{
top[x]=fst;//顶端元素top
id[x]=++tim;//新编号
w[id[x]]=p[x];//新权值
if(!son[x])
return ;
dfs2(son[x],fst);
for(int i=head[x];i;i=next1[i])
{
int v=to[i];
if(v==f[x]||v==son[x])
continue;
dfs2(v,v);
}
}
void updatetree(int s,int t,int c)
{
//以t为深度大的
c=c%mod;
while(top[s]!=top[t])
{
if(dep[top[s]]<dep[top[t]])
swap(s,t);
update(id[top[s]],id[s],c,1,n,1);
s=f[top[s]];
}
if(dep[s]>dep[t])
swap(s,t);
update(id[s],id[t],c,1,n,1);
}
int querytree(int s,int t)
{
int ans=0;
while(top[s]!=top[t])
{
if(dep[top[s]]<dep[top[t]])
swap(s,t);
ans+=query(id[top[s]],id[s],1,n,1);
ans=ans%mod;
s=f[top[s]];
}
if(dep[s]>dep[t])
swap(s,t);
ans+=query(id[s],id[t],1,n,1);
return ans%mod;
}
void updateson(int x,int c)//修改子树值
{
c=c%mod;
update(id[x],id[x]+siz[x]-1,c,1,n,1);
}
int queryson(int x)//查询子树和
{
return query(id[x],id[x]+siz[x]-1,1,n,1);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&r,&mod);
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs1(r,0,1);//根节点,父节点,深度
dfs2(r,r);
build(1,n,1);
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
if(x==1)//修改(a,b)的值为v
{
scanf("%d%d%d",&a,&b,&v);
updatetree(a,b,v);
}
else if(x==2){//查询(a,b)的简单路径
scanf("%d%d",&a,&b);
printf("%d\n",querytree(a,b));
}
else if(x==3)
{
scanf("%d%d",&a,&v);
updateson(a,v);
}
else{//查询a的子树
scanf("%d",&a);
printf("%d\n",queryson(a));
}
}
return 0;
}
poj-3966:https://vjudge.net/contest/308444#problem/A
ac:
#include<bits/stdc++.h>
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define MAXN 100005
using namespace std;
int to[MAXN],next1[MAXN],head[MAXN];
int p[MAXN];
int tot,n,m,tim;
int f[MAXN],dep[MAXN],son[MAXN],siz[MAXN];
int top[MAXN],id[MAXN],w[MAXN];
/**************************/
int sum[MAXN<<2],add2[MAXN<<2];
void pushup(int rt)//往上传
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int l,int r,int rt)//往下传
{
if(add2[rt])
{
int m=(l+r)>>1;
add2[rt<<1]+=add2[rt];//下传懒惰标记
add2[rt<<1|1]+=add2[rt];
sum[rt<<1]+=add2[rt]*(m-l+1);//下传修改儿子结点值
sum[rt<<1|1]+=add2[rt]*(r-(m+1)+1);
add2[rt]=0;//该点懒惰标记清零
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=w[l];
//scanf("%lld",&sum[rt]);
//sum[rt]=a[l];
return ;
}
int m=(l+r)>>1;
build(ls);
build(rs);
pushup(rt);//更新父节点,往上更新
}
void update(int a,int b,int v,int l,int r,int rt)
{
if(a<=l&&b>=r)//完全被包围
{
sum[rt]+=(r-l+1)*v;
add2[rt]+=v;
return ;
}
pushdown(l,r,rt);//要访问儿子结点,要把懒标记下传了
int m=(l+r)>>1;
if(a<=m)//包含左边,改左边
update(a,b,v,ls);
if(b>m)//包含右边,改右边
update(a,b,v,rs);
pushup(rt);
}
int query(int v,int l,int r,int rt)
{
if(l==r)
{
return sum[rt];
}
pushdown(l,r,rt);
int m=(l+r)>>1;
int res=0;
if(v<=m)
res=query(v,ls);
else
res=query(v,rs);
return res;
}
/**************************/
void init()
{
tim=tot=0;
memset(head,0,sizeof(head));
memset(son,0,sizeof(son));
memset(siz,0,sizeof(siz));
memset(add2,0,sizeof(add2));//注意懒惰标记要清空
}
void add(int u,int v)
{
to[++tot]=v;
next1[tot]=head[u];
head[u]=tot;
}
void dfs1(int x,int fa,int deep)//得f[],dep[],siz[],son[]
{
f[x]=fa;//父节点
dep[x]=deep;//深度
siz[x]=1;//子树大小
int maxson=-1;
for(int i=head[x];i;i=next1[i])
{
int v=to[i];
if(v==fa)
continue;
dfs1(v,x,deep+1);
siz[x]+=siz[v];
if(siz[v]>maxson)
{
maxson=siz[v];
son[x]=v;//重儿子
}
}
}
void dfs2(int x,int fst)//得top[],id[],w[]
{
top[x]=fst;//顶端元素top
id[x]=++tim;//新编号
w[id[x]]=p[x];//新权值
if(!son[x])
return ;
dfs2(son[x],fst);
for(int i=head[x];i;i=next1[i])
{
int v=to[i];
if(v==f[x]||v==son[x])
continue;
dfs2(v,v);
}
}
void updatetree(int s,int t,int c)
{
while(top[s]!=top[t])
{
if(dep[top[s]]<dep[top[t]])
swap(s,t);
update(id[top[s]],id[s],c,1,n,1);
s=f[top[s]];
}
if(dep[s]>dep[t])
swap(s,t);
update(id[s],id[t],c,1,n,1);
}
char str[5];
int main()
{
int q,a,b,v,x;
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
init();
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,n,1);
while(q--)
{
scanf("%s",&str);
if(str[0]=='I')
{
scanf("%d%d%d",&a,&b,&v);
updatetree(a,b,v);
}
else if(str[0]=='D')
{
scanf("%d%d%d",&a,&b,&v);
updatetree(a,b,-1*v);
}
else if(str[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",query(id[x],1,n,1));
}
}
}
return 0;
}