洛谷C语言支持malloc吗,洛谷 P3384 树链剖分(模板题)

题目描述

如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z

操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和

操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z

操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和

输入输出格式

输入格式:

第一行包含4个正整数N、M、R、P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。

接下来一行包含N个非负整数,分别依次表示各个节点上初始的数值。

接下来N-1行每行包含两个整数x、y,表示点x和点y只见连有一条边(保证无环且连通)

接下来M行每行包含若干个正整数,每行表示一个操作,格式如下:

操作1: 1 x y z

操作2: 2 x y

操作3: 3 x z

操作4: 4 x

输出格式:

输出包含若干行,分别依次表示每个操作2或操作4所得的结果(对P取模)

输入输出样例

输入样例#1:

5 5 2 24

7 3 7 8 0

1 2

1 5

3 1

4 1

3 4 2

3 2 2

4 5

1 5 1 3

2 1 3

输出样例#1:

2

21

说明

时空限制:1s,128M

数据规模:

对于30%的数据:N<=10,M<=10

对于70%的数据:N<=1000,M<=1000

对于100%的数据:N<=100000,M<=100000

(其实,纯随机生成的树LCA+暴力是能过的,可是,你觉得可能是纯随机的么233)

样例说明:

树的结构如下:

687e3be3c16bf247074126aaf1ae778b.png

各个操作如下:

70ed8c511aecae895662f45df64e89c0.png

故输出应依次为2、21(重要的事情说三遍:记得取模)

---------------------------------------x_x--------------------------------------

就是树链剖分

终于可以超熟练的在半小时内搞出树链剖分 好开心

代码如下:

#include

#include

#include

#define N 150000

#define For(i,x,y) for(int i=x;i<=y;++i)

using namespace std;

typedef long long LL;

int n,m,r,M;

struct Tree{

#define lson(x) (x<<1)

#define rson(x) ((x<<1)+1)

LL l[N*],r[N*],w[N*],sum[N*];

void upd(int x){sum[x]=(sum[lson(x)]+sum[rson(x)]+w[x]*(r[x]-l[x]+))%M;}

void build(int p,int L,int R)

{

l[p]=L;r[p]=R;w[p]=;

if(L==R)return;

int MID=(L+R)>>;

build(lson(p),L,MID);

build(rson(p),MID+,R);

}

void ins(int p,int x,int v)

{

int L=l[p],R=r[p];int MID=(L+R)>>;

if(L==R){

w[p]+=v;w[p]%=M;upd(p);return;

}

if(x<=MID)ins(lson(p),x,v);

else ins(rson(p),x,v);

upd(p);

}

void add(int x,int L,int R,int v)

{

int mid=(l[x]+r[x])>>;

if(l[x]==L&&r[x]==R)

{

w[x]+=v;w[x]%=M;upd(x);return;

}

if(R<=mid)add(lson(x),L,R,v);

if(L>mid)add(rson(x),L,R,v);

if(R>mid&&L<=mid)

{

add(lson(x),L,mid,v);

add(rson(x),mid+,R,v);

}

upd(x);

}

int getsum(int x,int L,int R)

{

int mid=(l[x]+r[x])>>;int tans=w[x]*(R-L+)%M;

if(l[x]==L&&r[x]==R)

{

return sum[x];

}

if(R<=mid)return (getsum(lson(x),L,R)+tans)%M;

if(L>mid)return (getsum(rson(x),L,R)+tans)%M;

if(R>mid&&L<=mid)

{

return (getsum(lson(x),L,mid)+getsum(rson(x),mid+,R)+tans)%M;

}

}

}T;

struct Graph{

struct E{

int next,to;

}edge[N*];

int head[N];int cnt;

bool vis[N];LL v[N],size[N],son[N],top[N],id[N],deep[N],fa[N],xid[N];

int sign;

void adde(int u,int v)

{

edge[++cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;

edge[++cnt].to=u;edge[cnt].next=head[v];head[v]=cnt;

}

void dfs1(int u)

{

size[u]=;int S=;

for(int i=head[u];i;i=edge[i].next)

{

int v=edge[i].to;

if(vis[v])continue;vis[v]=;

deep[v]=deep[u]+;fa[v]=u;

dfs1(v);

size[u]+=size[v];

if(!S||size[v]>size[S])S=v;

}

son[u]=S;

}

void dfs2(int u,int tp)

{

id[u]=++sign;

top[u]=tp;

if(!son[u]){xid[u]=sign;return;}

vis[son[u]]=;

dfs2(son[u],tp);

for(int i=head[u];i;i=edge[i].next)

{

int v=edge[i].to;if(vis[v])continue;

vis[v]=;dfs2(v,v);

}

xid[u]=sign;

}

void prework()

{

cin>>n>>m>>r>>M;

For(i,,n)scanf("%d",&v[i]);

For(i,,n-)

{

int u,v;scanf("%d%d",&u,&v);

adde(u,v);

}

vis[r]=;

dfs1(r);

memset(vis,,sizeof(vis));

vis[r]=;

dfs2(r,r);

T.build(,,n);

For(i,,n)T.ins(,id[i],v[i]);

}

void add1(int u,int v,int w)

{

if(deep[top[u]]

while(top[u]!=top[v])

{

T.add(,id[top[u]],id[u],w);

u=fa[top[u]];

if(deep[top[u]]

}

if(deep[u]

T.add(,id[v],id[u],w);

}

int get(int u,int v)

{

int ans=;

if(deep[top[u]]

while(top[u]!=top[v])

{

ans=(ans+T.getsum(,id[top[u]],id[u]))%M;

u=fa[top[u]];

if(deep[top[u]]

}

if(deep[u]

ans=(ans+T.getsum(,id[v],id[u]))%M;

return ans%M;

}

void add2(int u,int w)

{

T.add(,id[u],xid[u],w);

}

int get2(int u)

{

return T.getsum(,id[u],xid[u])%M;

}

}G;

int main()

{

G.prework();

For(t,,m)

{

int opt;

scanf("%d",&opt);

int u,v,w;

if(opt==)

{

scanf("%d%d%d",&u,&v,&w);

G.add1(u,v,w);

}

if(opt==)

{

scanf("%d%d",&u,&v);printf("%d\n",G.get(u,v));

}

if(opt==)

{

scanf("%d%d",&u,&w);G.add2(u,w);

}

if(opt==)

{

scanf("%d",&u);printf("%d\n",G.get2(u));

}

}

}

P.S.有没有觉得我的代码超帅啊 结构体凶在那里 @sjj118

洛谷P3384 树链剖分

如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x ...

洛谷 P3384树链剖分 题解

题面 挺好的一道树剖模板: 首先要学会最模板的树剖: 然后这道题要注意几个细节: 初始化时,seg[0]=1,seg[root]=1,top[root]=root,rev[1]=root; 在线段树上 ...

洛谷 &lbrack;P3384&rsqb; 树链剖分 模版

支持各种数据结构上树,注意取膜. #include #include #include #incl ...

BZOJ 2243 染色 &vert; 树链剖分模板题进阶版

BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

【算法学习】【洛谷】树链剖分 &amp&semi; P3384 【模板】树链剖分 P2146 软件包管理器

刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

洛谷 P2146 &lbrack;NOI2015&rsqb;软件包管理器 (树链剖分模板题)

题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...

bzoj1036 &lbrack;ZJOI2008&rsqb;树的统计Count 树链剖分模板题

[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...

【树链剖分】洛谷P3379 树链剖分求LCA

题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

BZOJ 1036 树的统计Count 树链剖分模板题

题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...

随机推荐

翻译:使用 ASP&period;NET MVC 4&comma; EF&comma; Knockoutjs and Bootstrap 设计和开发站点 - 3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值