》》题目
解题思路
没错,就是来水博客的,哈哈哈哈
详情请见BLOG》》树链剖分.
~~(我太j了,我太j了,逃)~
代码
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
ll p;
int n,m,root,k,x,y,cnt,z,s;
int w[2000010],head[2000010],dep[2000010],f[2000010],tot[2000010],son[2000010];
int id[2000010],ww[2000010],top[2000010];
struct c{
int x,next;
}a[2000100];
struct cc{
int x,y,l,add,size,w;
}t[2000100];
void add(int x,int y){
a[++k].x=y;
a[k].next=head[x];
head[x]=k;
}
void dfs1(int x,int fa){
dep[x]=dep[fa]+1;
f[x]=fa;
tot[x]=1;
int maxn=-1;
for(int i=head[x];i;i=a[i].next)
{
int y=a[i].x;
if(y==fa)continue;
dfs1(y,x);
tot[x]+=tot[y];
if(tot[y]>maxn)
{
maxn=tot[y];
son[x]=y;
}
}
}
void dfs2(int x,int topf){
id[x]=++cnt;
ww[cnt]=w[x];
top[x]=topf;
if(!son[x])return;
dfs2(son[x],topf);
for(int i=head[x];i;i=a[i].next)
{
int y=a[i].x;
if(!id[y])
dfs2(y,y);
}
}
void up(int k){
t[k].w=(t[k*2].w+t[k*2+1].w)%p;
}
void pushdown(int k){
if(!t[k].add)return;
t[k*2].add=(t[k*2].add+t[k].add)%p;
t[k*2+1].add=(t[k*2+1].add+t[k].add)%p;
t[k*2].w=(t[k*2].w+t[k*2].size*t[k].add)%p;
t[k*2+1].w=(t[k*2+1].w+t[k*2+1].size*t[k].add)%p;
t[k].add=0;
}
void build(int k,int l,int r)
{
t[k].x=l,t[k].y=r,t[k].size=r-l+1;
if(l==r)
{
t[k].w=ww[l];
return;
}
int mid=(l+r)>>1;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
up(k);
}
void pushadd(int k,int l,int r,int v){
if(t[k].x>=l&&t[k].y<=r)
{
t[k].w+=t[k].size*v;
t[k].add+=v;
return;
}
int mid=(t[k].x+t[k].y)/2;
pushdown(k);
if(l<=mid)pushadd(k*2,l,r,v);
if(r>mid)pushadd(k*2+1,l,r,v);
up(k);
}
void Treeadd(int x,int y,int v){
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
pushadd(1,id[top[x]],id[x],v);
x=f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
pushadd(1,id[x],id[y],v);
}
int pushsum(int k,int l,int r){
int ans=0;
if(t[k].x>=l&&t[k].y<=r)
return t[k].w;
int mid=(t[k].x+t[k].y)/2;
pushdown(k);
if(l<=mid)ans=(ans+pushsum(k*2,l,r))%p;
if(r>mid)ans=(ans+pushsum(k*2+1,l,r))%p;
return ans;
}
int Treesum(int x,int y){
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=(ans+pushsum(1,id[top[x]],id[x]))%p;
x=f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans=(ans+pushsum(1,id[x],id[y]))%p;
return ans;
}
int main(){
scanf("%d%d%d%d",&n,&m,&root,&p);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(root,0);
dfs2(root,root);
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&s);
if(s==1)
{
scanf("%d%d%d",&x,&y,&z);
Treeadd(x,y,z%p);
}
if(s==2)
{
scanf("%d%d",&x,&y);
printf("%d\n",Treesum(x,y));
}
if(s==3)
{
scanf("%d%d",&x,&z);
pushadd(1,id[x],id[x]+tot[x]-1,z%p);
}
if(s==4)
{
scanf("%d",&x);
printf("%d\n",pushsum(1,id[x],id[x]+tot[x]-1));
}
}
}
/*
8 10 2 448348
458 718 447 857 633 264 238 944
1 2
2 3
3 4
6 2
1 5
5 7
8 6
3 7 611
4 6
3 1 267
3 2 111
1 6 3 153
3 7 673
4 8
2 6 1
4 7
3 4 228
1208
1055
2346
1900
*/