Ahead
10.5.2018 第一篇文章 欢迎指正
分析
树链剖分模板题,如果有时间的话在上树剖算法分析吧
这道大紫题
剖完(切完拉完。。。。)
然后加上线段树维护
- 注意下标的处理(在映射之间傻傻分不清)
- 查询和更新直接沿着边跑
- 对于子树是序列加大小
- 带了快读自动忽略
- dfs1 用于保存树的信息
dfs2 来连接太子
努力憋文字摘要不能有代码! ! !代码
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;
char c=getchar();
while(c<'0' || c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c<='9' && c>='0')
{
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
return x*f;
}
const int N = 1e5+100;
int n,m,root,mod;
int w[N];
int to[N<<1],nxt[N<<1],last[N],len;
inline void ins(int x,int y)
{
to[++len]=y, nxt[len]=last[x], last[x]=len;
}
int tot[N],dep[N],son[N],fa[N];
void dfs1(int x)
{
tot[x]=1;
for(int k=last[x]; k; k=nxt[k])
{
int y=to[k];
if(y!=fa[x])
{
dep[y]=dep[x]+1;
fa[y]=x;
dfs1(y);
tot[x]+=tot[y];
if(tot[y]>tot[son[x]]) son[x]=y;
}
}
}
int pos[N],top[N],rpos[N],tim;
void dfs2(int x,int tp)
{
pos[x]=++tim, rpos[tim]=x, top[x]=tp;
if(!son[x]) return;
dfs2(son[x],tp);
for(int k=last[x]; k; k=nxt[k])
{
int y=to[k];
if(y!=fa[x] && y!=son[x]) dfs2(y,y);
}
}
struct node
{
int l,r,val,lazy;
} e[N<<2];
inline void push_up(int now)
{
e[now].val=(e[now<<1].val+e[now<<1|1].val)%mod;
}
inline void push_down(int now)
{
e[now<<1].val+=e[now].lazy*(e[now<<1].r-e[now<<1].l+1);
e[now<<1].val%=mod;
e[now<<1].lazy+=e[now].lazy;
e[now<<1|1].val+=e[now].lazy*(e[now<<1|1].r-e[now<<1|1].l+1);
e[now<<1|1].val%=mod;
e[now<<1|1].lazy+=e[now].lazy;
e[now].lazy=0;
}
void bt(int now ,int l,int r)
{
e[now].l=l,e[now].r=r;
if(l>=r)
{
e[now].val=w[rpos[l]];
return ;
}
int mid=(l+r)>>1;
bt(now<<1,l,mid);
bt(now<<1|1,mid+1,r);
push_up(now);
}
void up_data(int now ,int l,int r,int k)
{
if(e[now].l==l && e[now].r==r)
{
e[now].val+=k*(r-l+1);
e[now].val%=mod;
e[now].lazy+=k;
return;
}
if(e[now].lazy) push_down(now);
int mid=(e[now].l+e[now].r)>>1;
if(r<=mid) up_data(now<<1,l,r,k);
else if(l>mid) up_data(now<<1|1,l,r,k);
else
{
up_data(now<<1,l,mid,k);
up_data(now<<1|1,mid+1,r,k);
}
push_up(now);
}
int quary(int now ,int l,int r)
{
if(e[now].l==l && e[now].r==r) return e[now].val;
int ans=0;
if(e[now].lazy) push_down(now);
int mid=(e[now].l+e[now].r)>>1;
if(r<=mid) ans=quary(now<<1,l,r)%mod;
else if(l>mid) ans=quary(now<<1|1,l,r)%mod;
else
{
ans+=quary(now<<1,l,mid)%mod;
ans+=quary(now<<1|1,mid+1,r)%mod;
ans%=mod;
}
push_up(now);
return ans;
}
inline void updata(int x,int y,int k)
{
int tx=top[x],ty=top[y];
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(x,y),swap(tx,ty);
up_data(1,pos[ty],pos[y],k);
y=fa[ty],ty=top[y];
}
if(dep[x]>dep[y]) swap(x,y);
up_data(1,pos[x],pos[y],k);
}
inline int ask(int x,int y)
{
int ans=0,tx=top[x],ty=top[y];
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(x,y),swap(tx,ty);
ans+=quary(1,pos[ty],pos[y]);
ans%=mod;
y=fa[ty],ty=top[y];
}
if(dep[x]>dep[y]) swap(x,y);
ans+=quary(1,pos[x],pos[y])%mod;
ans%=mod;
return ans;
}
int main()
{
int q,x,y,c;
n=read(),m=read(),root=read(),mod=read();
for(int i=1; i<=n; ++i) w[i]=read();
for(int i=1; i<n; ++i)
{
x=read(),y=read();
ins(x,y);
ins(y,x);
}
dep[root]=1;
dfs1(root);
dfs2(root,root);
/*for(int i=1; i<=n; ++i)
printf("ddd %d\n",fa[i]);
system("pause");*/
bt(1,1,tim);
while(m--)
{
q=read();
if(q==1)
{
x=read(),y=read(),c=read();
updata(x,y,c);
}
else if(q==2)
{
x=read(),y=read();
printf("%d\n",ask(x,y)%mod);
}
else if(q==3)
{
x=read(),y=read();
up_data(1,pos[x],pos[x]+tot[x]-1,y);
}
else if(q==4)
{
x=read();
printf("%d\n",quary(1,pos[x],pos[x]+tot[x]-1)%mod);
}
}
return 0;
}